rasa-pro 3.11.13__py3-none-any.whl → 3.11.15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of rasa-pro might be problematic. Click here for more details.

Files changed (36) hide show
  1. rasa/api.py +4 -0
  2. rasa/cli/arguments/default_arguments.py +13 -1
  3. rasa/cli/arguments/train.py +2 -0
  4. rasa/cli/train.py +1 -0
  5. rasa/constants.py +2 -0
  6. rasa/core/nlg/contextual_response_rephraser.py +40 -14
  7. rasa/core/nlg/summarize.py +37 -5
  8. rasa/core/persistor.py +55 -20
  9. rasa/core/policies/enterprise_search_policy.py +10 -7
  10. rasa/core/policies/intentless_policy.py +17 -11
  11. rasa/core/run.py +7 -2
  12. rasa/dialogue_understanding/coexistence/llm_based_router.py +11 -6
  13. rasa/dialogue_understanding/generator/constants.py +6 -4
  14. rasa/dialogue_understanding/generator/multi_step/multi_step_llm_command_generator.py +1 -1
  15. rasa/dialogue_understanding/generator/single_step/single_step_llm_command_generator.py +1 -1
  16. rasa/dialogue_understanding/processor/command_processor_component.py +4 -4
  17. rasa/engine/recipes/default_recipe.py +26 -2
  18. rasa/llm_fine_tuning/paraphrasing/conversation_rephraser.py +4 -2
  19. rasa/model_manager/config.py +3 -1
  20. rasa/model_manager/model_api.py +1 -2
  21. rasa/model_manager/runner_service.py +8 -4
  22. rasa/model_manager/trainer_service.py +1 -0
  23. rasa/model_training.py +12 -3
  24. rasa/server.py +6 -2
  25. rasa/shared/constants.py +6 -0
  26. rasa/shared/providers/_configs/azure_openai_client_config.py +14 -10
  27. rasa/shared/providers/_configs/openai_client_config.py +13 -9
  28. rasa/shared/providers/embedding/_base_litellm_embedding_client.py +3 -0
  29. rasa/shared/providers/llm/_base_litellm_client.py +5 -2
  30. rasa/shared/utils/llm.py +8 -2
  31. rasa/version.py +1 -1
  32. {rasa_pro-3.11.13.dist-info → rasa_pro-3.11.15.dist-info}/METADATA +1 -1
  33. {rasa_pro-3.11.13.dist-info → rasa_pro-3.11.15.dist-info}/RECORD +36 -36
  34. {rasa_pro-3.11.13.dist-info → rasa_pro-3.11.15.dist-info}/NOTICE +0 -0
  35. {rasa_pro-3.11.13.dist-info → rasa_pro-3.11.15.dist-info}/WHEEL +0 -0
  36. {rasa_pro-3.11.13.dist-info → rasa_pro-3.11.15.dist-info}/entry_points.txt +0 -0
@@ -255,7 +255,7 @@ class MultiStepLLMCommandGenerator(LLMBasedCommandGenerator):
255
255
  skip_question_re = re.compile(r"SkipQuestion\(\)")
256
256
  knowledge_re = re.compile(r"SearchAndReply\(\)")
257
257
  humand_handoff_re = re.compile(r"HumanHandoff\(\)")
258
- clarify_re = re.compile(r"Clarify\(([\"\'a-zA-Z0-9_, ]+)\)")
258
+ clarify_re = re.compile(r"Clarify\(([\"\'a-zA-Z0-9_\-, ]+)\)")
259
259
  cannot_handle_re = re.compile(r"CannotHandle\(\)")
260
260
 
261
261
  for action in actions.strip().splitlines():
@@ -329,7 +329,7 @@ class SingleStepLLMCommandGenerator(LLMBasedCommandGenerator):
329
329
  skip_question_re = re.compile(r"SkipQuestion\(\)")
330
330
  knowledge_re = re.compile(r"SearchAndReply\(\)")
331
331
  humand_handoff_re = re.compile(r"HumanHandoff\(\)")
332
- clarify_re = re.compile(r"Clarify\(([\"\'a-zA-Z0-9_, ]+)\)")
332
+ clarify_re = re.compile(r"Clarify\(([\"\'a-zA-Z0-9_\-, ]+)\)")
333
333
  repeat_re = re.compile(r"RepeatLastBotMessages\(\)")
334
334
 
335
335
  for action in actions.strip().splitlines():
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Any, Dict, List, Text
4
- import rasa.dialogue_understanding.processor.command_processor
3
+ from typing import Any, Dict, List, Optional, Text
5
4
 
5
+ import rasa.dialogue_understanding.processor.command_processor
6
6
  from rasa.engine.graph import ExecutionContext, GraphComponent
7
7
  from rasa.engine.storage.resource import Resource
8
8
  from rasa.engine.storage.storage import ModelStorage
@@ -37,8 +37,8 @@ class CommandProcessorComponent(GraphComponent):
37
37
  self,
38
38
  tracker: DialogueStateTracker,
39
39
  flows: FlowsList,
40
- story_graph: StoryGraph,
41
- domain: Domain,
40
+ domain: Optional[Domain] = None,
41
+ story_graph: Optional[StoryGraph] = None,
42
42
  ) -> List[Event]:
43
43
  """Execute commands to update tracker state."""
44
44
  return rasa.dialogue_understanding.processor.command_processor.execute_commands(
@@ -382,7 +382,9 @@ class DefaultV1Recipe(Recipe):
382
382
  return preprocessors
383
383
 
384
384
  def _get_needs_from_args(
385
- self, component: Type[GraphComponent], fn_name: str
385
+ self,
386
+ component: Type[GraphComponent],
387
+ fn_name: str,
386
388
  ) -> Dict[str, str]:
387
389
  """Get the needed arguments from the method on the component.
388
390
 
@@ -420,6 +422,7 @@ class DefaultV1Recipe(Recipe):
420
422
  parameters = {
421
423
  name
422
424
  for name, param in sig.parameters.items()
425
+ # only consider parameters which are positional or keyword
423
426
  if param.kind == param.POSITIONAL_OR_KEYWORD
424
427
  }
425
428
 
@@ -736,8 +739,28 @@ class DefaultV1Recipe(Recipe):
736
739
  predict_config, predict_nodes, train_nodes, preprocessors
737
740
  )
738
741
 
742
+ # The `story_graph_provider` is only needed if the intentless policy is used.
743
+ # If it is not used, we can remove it from the nodes as it slows down the
744
+ # loading time if users have a large number of stories.
745
+ if not self._intentless_policy_used(predict_nodes):
746
+ # Removes the `story_graph_provider` from the nodes
747
+ predict_nodes.pop("story_graph_provider", None)
748
+ if "command_processor" in predict_nodes:
749
+ # Removes story_graph from the command processor inputs
750
+ predict_nodes["command_processor"].needs.pop("story_graph", None)
751
+
739
752
  return predict_nodes
740
753
 
754
+ @staticmethod
755
+ def _intentless_policy_used(nodes: Dict[Text, SchemaNode]) -> bool:
756
+ """Checks if the intentless policy is used in the nodes."""
757
+ from rasa.core import IntentlessPolicy
758
+
759
+ for schema_node in nodes.values():
760
+ if schema_node.matches_type(IntentlessPolicy):
761
+ return True
762
+ return False
763
+
741
764
  def _add_nlu_predict_nodes(
742
765
  self,
743
766
  last_run_node: Text,
@@ -908,7 +931,8 @@ class DefaultV1Recipe(Recipe):
908
931
  predict_nodes["command_processor"] = SchemaNode(
909
932
  **DEFAULT_PREDICT_KWARGS,
910
933
  needs=self._get_needs_from_args(
911
- CommandProcessorComponent, "execute_commands"
934
+ CommandProcessorComponent,
935
+ "execute_commands",
912
936
  ),
913
937
  uses=CommandProcessorComponent,
914
938
  fn="execute_commands",
@@ -10,11 +10,13 @@ from rasa.llm_fine_tuning.paraphrasing.rephrased_user_message import (
10
10
  RephrasedUserMessage,
11
11
  )
12
12
  from rasa.shared.constants import (
13
+ MAX_COMPLETION_TOKENS_CONFIG_KEY,
13
14
  MODEL_NAME_CONFIG_KEY,
14
15
  MODEL_CONFIG_KEY,
15
16
  LLM_CONFIG_KEY,
16
17
  PROMPT_TEMPLATE_CONFIG_KEY,
17
18
  PROVIDER_CONFIG_KEY,
19
+ TEMPERATURE_CONFIG_KEY,
18
20
  TIMEOUT_CONFIG_KEY,
19
21
  )
20
22
  from rasa.shared.exceptions import ProviderClientAPIException
@@ -38,8 +40,8 @@ DEFAULT_LLM_CONFIG = {
38
40
  PROVIDER_CONFIG_KEY: OPENAI_PROVIDER,
39
41
  MODEL_CONFIG_KEY: "gpt-4o-mini",
40
42
  TIMEOUT_CONFIG_KEY: 7,
41
- "temperature": 0.0,
42
- "max_tokens": 4096,
43
+ TEMPERATURE_CONFIG_KEY: 0.0,
44
+ MAX_COMPLETION_TOKENS_CONFIG_KEY: 4096,
43
45
  }
44
46
 
45
47
  structlogger = structlog.get_logger()
@@ -1,6 +1,8 @@
1
1
  import sys
2
2
  import os
3
3
 
4
+ from rasa.constants import RASA_REMOTE_STORAGE_ENV_VAR_NAME
5
+
4
6
  DEFAULT_SERVER_BASE_WORKING_DIRECTORY = "working-data"
5
7
 
6
8
  SERVER_BASE_WORKING_DIRECTORY = os.environ.get(
@@ -12,7 +14,7 @@ SERVER_PORT = os.environ.get("RASA_MODEL_SERVER_PORT", 8000)
12
14
  SERVER_BASE_URL = os.environ.get("RASA_MODEL_SERVER_BASE_URL", None)
13
15
 
14
16
  # defaults to storing on the local hard drive
15
- SERVER_MODEL_REMOTE_STORAGE = os.environ.get("RASA_REMOTE_STORAGE", None)
17
+ SERVER_MODEL_REMOTE_STORAGE = os.environ.get(RASA_REMOTE_STORAGE_ENV_VAR_NAME, None)
16
18
 
17
19
  # The path to the python executable that is running this script
18
20
  # we will use the same python to run training / bots
@@ -531,8 +531,7 @@ def size_of_model(model_name: str) -> Optional[int]:
531
531
  model_name=model_file_name,
532
532
  )
533
533
  return fetch_size_of_remote_model(
534
- model_file_name,
535
- config.SERVER_MODEL_REMOTE_STORAGE,
534
+ model_file_name, config.SERVER_MODEL_REMOTE_STORAGE, model_path
536
535
  )
537
536
  raise ModelNotFound("Model not found.")
538
537
 
@@ -166,13 +166,13 @@ def fetch_remote_model_to_dir(
166
166
  ) -> str:
167
167
  """Fetch the model from remote storage.
168
168
 
169
- Returns the path to the model diretory.
169
+ Returns the path to the model directory.
170
170
  """
171
171
  from rasa.core.persistor import get_persistor
172
172
 
173
173
  persistor = get_persistor(storage_type)
174
174
 
175
- # we now there must be a persistor, because the config is set
175
+ # we know there must be a persistor, because the config is set
176
176
  # this is here to please the type checker for the call below
177
177
  assert persistor is not None
178
178
 
@@ -182,7 +182,9 @@ def fetch_remote_model_to_dir(
182
182
  raise ModelNotFound() from e
183
183
 
184
184
 
185
- def fetch_size_of_remote_model(model_name: str, storage_type: str) -> int:
185
+ def fetch_size_of_remote_model(
186
+ model_name: str, storage_type: str, model_path: str
187
+ ) -> int:
186
188
  """Fetch the size of the model from remote storage."""
187
189
  from rasa.core.persistor import get_persistor
188
190
 
@@ -192,7 +194,9 @@ def fetch_size_of_remote_model(model_name: str, storage_type: str) -> int:
192
194
  # this is here to please the type checker for the call below
193
195
  assert persistor is not None
194
196
 
195
- return persistor.size_of_persisted_model(model_name=model_name)
197
+ return persistor.size_of_persisted_model(
198
+ model_name=model_name, target_path=model_path
199
+ )
196
200
 
197
201
 
198
202
  def start_bot_process(
@@ -276,6 +276,7 @@ def start_training_process(
276
276
  "--keep-local-model-copy",
277
277
  "--remote-storage",
278
278
  config.SERVER_MODEL_REMOTE_STORAGE,
279
+ "--remote-root-only",
279
280
  ]
280
281
  )
281
282
 
rasa/model_training.py CHANGED
@@ -158,6 +158,7 @@ async def train(
158
158
  remote_storage: Optional[StorageType] = None,
159
159
  file_importer: Optional[TrainingDataImporter] = None,
160
160
  keep_local_model_copy: bool = False,
161
+ remote_root_only: bool = False,
161
162
  ) -> TrainingResult:
162
163
  """Trains a Rasa model (Core and NLU).
163
164
 
@@ -185,6 +186,8 @@ async def train(
185
186
  If it is not provided, a new instance will be created.
186
187
  keep_local_model_copy: If `True` the model will be stored locally even if
187
188
  remote storage is configured.
189
+ remote_root_only: If `True`, the model will be stored in the root of the
190
+ remote model storage.
188
191
 
189
192
  Returns:
190
193
  An instance of `TrainingResult`.
@@ -267,6 +270,7 @@ async def train(
267
270
  dry_run=dry_run,
268
271
  remote_storage=remote_storage,
269
272
  keep_local_model_copy=keep_local_model_copy,
273
+ remote_root_only=remote_root_only,
270
274
  **(core_additional_arguments or {}),
271
275
  **(nlu_additional_arguments or {}),
272
276
  )
@@ -282,6 +286,7 @@ async def _train_graph(
282
286
  dry_run: bool = False,
283
287
  remote_storage: Optional[StorageType] = None,
284
288
  keep_local_model_copy: bool = False,
289
+ remote_root_only: bool = False,
285
290
  **kwargs: Any,
286
291
  ) -> TrainingResult:
287
292
  if model_to_finetune:
@@ -363,7 +368,9 @@ async def _train_graph(
363
368
  is_finetuning=is_finetuning,
364
369
  )
365
370
  if remote_storage:
366
- push_model_to_remote_storage(full_model_path, remote_storage)
371
+ push_model_to_remote_storage(
372
+ full_model_path, remote_storage, remote_root_only
373
+ )
367
374
  if not keep_local_model_copy:
368
375
  full_model_path.unlink()
369
376
  structlogger.info(
@@ -581,14 +588,16 @@ async def train_nlu(
581
588
  ).model
582
589
 
583
590
 
584
- def push_model_to_remote_storage(model_path: Path, remote_storage: StorageType) -> None:
591
+ def push_model_to_remote_storage(
592
+ model_path: Path, remote_storage: StorageType, remote_root_only: bool = False
593
+ ) -> None:
585
594
  """Push model to remote storage."""
586
595
  from rasa.core.persistor import get_persistor
587
596
 
588
597
  persistor = get_persistor(remote_storage)
589
598
 
590
599
  if persistor is not None:
591
- persistor.persist(str(model_path))
600
+ persistor.persist(str(model_path), remote_root_only)
592
601
 
593
602
  else:
594
603
  raise RasaException(
rasa/server.py CHANGED
@@ -522,12 +522,15 @@ def configure_cors(
522
522
  )
523
523
 
524
524
 
525
- def add_root_route(app: Sanic) -> None:
525
+ def add_root_route(app: Sanic, is_inspector_enabled: bool = False) -> None:
526
526
  """Add '/' route to return hello."""
527
527
 
528
528
  @app.get("/")
529
529
  async def hello(request: Request) -> HTTPResponse:
530
530
  """Check if the server is running and responds with the version."""
531
+ if not is_inspector_enabled:
532
+ return response.text("Hello from Rasa: " + rasa.__version__)
533
+
531
534
  html_content = f"""
532
535
  <html>
533
536
  <body>
@@ -688,6 +691,7 @@ def create_app(
688
691
  jwt_private_key: Optional[Text] = None,
689
692
  jwt_method: Text = "HS256",
690
693
  endpoints: Optional[AvailableEndpoints] = None,
694
+ is_inspector_enabled: bool = False,
691
695
  ) -> Sanic:
692
696
  """Class representing a Rasa HTTP server."""
693
697
  app = Sanic("rasa_server")
@@ -733,7 +737,7 @@ def create_app(
733
737
  ) -> HTTPResponse:
734
738
  return response.json(exception.error_info, status=exception.status)
735
739
 
736
- add_root_route(app)
740
+ add_root_route(app, is_inspector_enabled)
737
741
 
738
742
  @app.get("/version")
739
743
  async def version(request: Request) -> HTTPResponse:
rasa/shared/constants.py CHANGED
@@ -181,6 +181,12 @@ PROVIDER_CONFIG_KEY = "provider"
181
181
  REQUEST_TIMEOUT_CONFIG_KEY = "request_timeout" # deprecated
182
182
  TIMEOUT_CONFIG_KEY = "timeout"
183
183
 
184
+ LOGIT_BIAS_CONFIG_KEY = "logit_bias"
185
+ MAX_RETRIES_CONFIG_KEY = "max_retries"
186
+ TEMPERATURE_CONFIG_KEY = "temperature"
187
+ MAX_COMPLETION_TOKENS_CONFIG_KEY = "max_completion_tokens"
188
+ MAX_TOKENS_CONFIG_KEY = "max_tokens"
189
+
184
190
  DEPLOYMENT_NAME_CONFIG_KEY = "deployment_name"
185
191
  DEPLOYMENT_CONFIG_KEY = "deployment"
186
192
  EMBEDDINGS_CONFIG_KEY = "embeddings"
@@ -4,26 +4,28 @@ from typing import Any, Dict, Optional
4
4
  import structlog
5
5
 
6
6
  from rasa.shared.constants import (
7
- MODEL_CONFIG_KEY,
8
- MODEL_NAME_CONFIG_KEY,
9
- OPENAI_API_BASE_CONFIG_KEY,
10
7
  API_BASE_CONFIG_KEY,
11
- OPENAI_API_TYPE_CONFIG_KEY,
12
8
  API_TYPE_CONFIG_KEY,
13
- OPENAI_API_VERSION_CONFIG_KEY,
14
9
  API_VERSION_CONFIG_KEY,
10
+ AZURE_API_TYPE,
11
+ AZURE_OPENAI_PROVIDER,
15
12
  DEPLOYMENT_CONFIG_KEY,
16
13
  DEPLOYMENT_NAME_CONFIG_KEY,
17
14
  ENGINE_CONFIG_KEY,
18
- RASA_TYPE_CONFIG_KEY,
19
15
  LANGCHAIN_TYPE_CONFIG_KEY,
20
- STREAM_CONFIG_KEY,
16
+ MAX_COMPLETION_TOKENS_CONFIG_KEY,
17
+ MAX_TOKENS_CONFIG_KEY,
18
+ MODEL_CONFIG_KEY,
19
+ MODEL_NAME_CONFIG_KEY,
21
20
  N_REPHRASES_CONFIG_KEY,
21
+ OPENAI_API_BASE_CONFIG_KEY,
22
+ OPENAI_API_TYPE_CONFIG_KEY,
23
+ OPENAI_API_VERSION_CONFIG_KEY,
24
+ PROVIDER_CONFIG_KEY,
25
+ RASA_TYPE_CONFIG_KEY,
22
26
  REQUEST_TIMEOUT_CONFIG_KEY,
27
+ STREAM_CONFIG_KEY,
23
28
  TIMEOUT_CONFIG_KEY,
24
- PROVIDER_CONFIG_KEY,
25
- AZURE_OPENAI_PROVIDER,
26
- AZURE_API_TYPE,
27
29
  )
28
30
  from rasa.shared.providers._configs.utils import (
29
31
  resolve_aliases,
@@ -51,6 +53,8 @@ DEPRECATED_ALIASES_TO_STANDARD_KEY_MAPPING = {
51
53
  MODEL_NAME_CONFIG_KEY: MODEL_CONFIG_KEY,
52
54
  # Timeout aliases
53
55
  REQUEST_TIMEOUT_CONFIG_KEY: TIMEOUT_CONFIG_KEY,
56
+ # Max tokens aliases
57
+ MAX_TOKENS_CONFIG_KEY: MAX_COMPLETION_TOKENS_CONFIG_KEY,
54
58
  }
55
59
 
56
60
  REQUIRED_KEYS = [DEPLOYMENT_CONFIG_KEY]
@@ -4,23 +4,25 @@ from typing import Any, Dict, Optional
4
4
  import structlog
5
5
 
6
6
  from rasa.shared.constants import (
7
+ API_BASE_CONFIG_KEY,
8
+ API_TYPE_CONFIG_KEY,
9
+ API_VERSION_CONFIG_KEY,
10
+ LANGCHAIN_TYPE_CONFIG_KEY,
11
+ MAX_COMPLETION_TOKENS_CONFIG_KEY,
12
+ MAX_TOKENS_CONFIG_KEY,
7
13
  MODEL_CONFIG_KEY,
8
14
  MODEL_NAME_CONFIG_KEY,
15
+ N_REPHRASES_CONFIG_KEY,
9
16
  OPENAI_API_BASE_CONFIG_KEY,
10
- API_BASE_CONFIG_KEY,
17
+ OPENAI_API_TYPE,
11
18
  OPENAI_API_TYPE_CONFIG_KEY,
12
- API_TYPE_CONFIG_KEY,
13
19
  OPENAI_API_VERSION_CONFIG_KEY,
14
- API_VERSION_CONFIG_KEY,
20
+ OPENAI_PROVIDER,
21
+ PROVIDER_CONFIG_KEY,
15
22
  RASA_TYPE_CONFIG_KEY,
16
- LANGCHAIN_TYPE_CONFIG_KEY,
17
- STREAM_CONFIG_KEY,
18
- N_REPHRASES_CONFIG_KEY,
19
23
  REQUEST_TIMEOUT_CONFIG_KEY,
24
+ STREAM_CONFIG_KEY,
20
25
  TIMEOUT_CONFIG_KEY,
21
- PROVIDER_CONFIG_KEY,
22
- OPENAI_API_TYPE,
23
- OPENAI_PROVIDER,
24
26
  )
25
27
  from rasa.shared.providers._configs.utils import (
26
28
  resolve_aliases,
@@ -46,6 +48,8 @@ DEPRECATED_ALIASES_TO_STANDARD_KEY_MAPPING = {
46
48
  OPENAI_API_VERSION_CONFIG_KEY: API_VERSION_CONFIG_KEY,
47
49
  # Timeout aliases
48
50
  REQUEST_TIMEOUT_CONFIG_KEY: TIMEOUT_CONFIG_KEY,
51
+ # Max tokens aliases
52
+ MAX_TOKENS_CONFIG_KEY: MAX_COMPLETION_TOKENS_CONFIG_KEY,
49
53
  }
50
54
 
51
55
  REQUIRED_KEYS = [MODEL_CONFIG_KEY]
@@ -70,7 +70,10 @@ class _BaseLiteLLMEmbeddingClient:
70
70
  def _embedding_fn_args(self) -> Dict[str, Any]:
71
71
  """Returns the arguments to be passed to the embedding function."""
72
72
  return {
73
+ # Parameters set through config, can override drop_params
73
74
  **self._litellm_extra_parameters,
75
+ # Model name is constructed in the LiteLLM format from the provided config
76
+ # Non-overridable to ensure consistency
74
77
  "model": self._litellm_model_name,
75
78
  }
76
79
 
@@ -85,12 +85,15 @@ class _BaseLiteLLMClient:
85
85
  @property
86
86
  def _completion_fn_args(self) -> dict:
87
87
  return {
88
- **self._litellm_extra_parameters,
89
- "model": self._litellm_model_name,
90
88
  # Since all providers covered by LiteLLM use the OpenAI format, but
91
89
  # not all support every OpenAI parameter, raise an exception if
92
90
  # provider/model uses unsupported parameter
93
91
  "drop_params": False,
92
+ # All other parameters set through config, can override drop_params
93
+ **self._litellm_extra_parameters,
94
+ # Model name is constructed in the LiteLLM format from the provided config
95
+ # Non-overridable to ensure consistency
96
+ "model": self._litellm_model_name,
94
97
  }
95
98
 
96
99
  def validate_client_setup(self) -> None:
rasa/shared/utils/llm.py CHANGED
@@ -5,6 +5,7 @@ from typing import (
5
5
  Any,
6
6
  Callable,
7
7
  Dict,
8
+ List,
8
9
  Optional,
9
10
  Text,
10
11
  Type,
@@ -187,6 +188,7 @@ def tracker_as_readable_transcript(
187
188
  human_prefix: str = USER,
188
189
  ai_prefix: str = AI,
189
190
  max_turns: Optional[int] = 20,
191
+ turns_wrapper: Optional[Callable[[List[str]], List[str]]] = None,
190
192
  ) -> str:
191
193
  """Creates a readable dialogue from a tracker.
192
194
 
@@ -195,6 +197,7 @@ def tracker_as_readable_transcript(
195
197
  human_prefix: the prefix to use for human utterances
196
198
  ai_prefix: the prefix to use for ai utterances
197
199
  max_turns: the maximum number of turns to include in the transcript
200
+ turns_wrapper: optional function to wrap the turns in a custom way
198
201
 
199
202
  Example:
200
203
  >>> tracker = Tracker(
@@ -231,8 +234,11 @@ def tracker_as_readable_transcript(
231
234
  elif isinstance(event, BotUttered):
232
235
  transcript.append(f"{ai_prefix}: {sanitize_message_for_prompt(event.text)}")
233
236
 
234
- if max_turns:
235
- transcript = transcript[-max_turns:]
237
+ # turns_wrapper to count multiple utterances by bot/user as single turn
238
+ if turns_wrapper:
239
+ transcript = turns_wrapper(transcript)
240
+ # otherwise, just take the last `max_turns` lines of the transcript
241
+ transcript = transcript[-max_turns if max_turns is not None else None :]
236
242
 
237
243
  return "\n".join(transcript)
238
244
 
rasa/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  # this file will automatically be changed,
2
2
  # do not add anything but the version number here!
3
- __version__ = "3.11.13"
3
+ __version__ = "3.11.15"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rasa-pro
3
- Version: 3.11.13
3
+ Version: 3.11.15
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