rasa-pro 3.10.22__py3-none-any.whl → 3.10.23__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.

@@ -22,10 +22,11 @@ from rasa.shared.core.flows.flow_step_links import (
22
22
  from rasa.shared.core.flows.flow_step_sequence import FlowStepSequence
23
23
  from rasa.shared.core.flows.nlu_trigger import NLUTriggers
24
24
  from rasa.shared.core.flows.steps import (
25
+ ActionFlowStep,
26
+ CallFlowStep,
25
27
  CollectInformationFlowStep,
26
28
  EndFlowStep,
27
29
  StartFlowStep,
28
- ActionFlowStep,
29
30
  )
30
31
  from rasa.shared.core.flows.steps.constants import (
31
32
  CONTINUE_STEP_PREFIX,
@@ -397,161 +398,156 @@ class Flow:
397
398
  and a set of visited step IDs to prevent revisiting steps.
398
399
  It calls `go_over_steps` to recursively explore and fill the paths list.
399
400
  """
400
- flow_paths_list = FlowPathsList(self.id, paths=[])
401
- steps: List[FlowStep] = self.steps
401
+ all_paths = FlowPathsList(self.id, paths=[])
402
+ start_step: FlowStep = self.first_step_in_flow()
402
403
  current_path: FlowPath = FlowPath(flow=self.id, nodes=[])
403
- step_ids_visited: Set[str] = set()
404
-
405
- self._go_over_steps(steps, current_path, flow_paths_list, step_ids_visited)
404
+ visited_step_ids: Set[str] = set()
406
405
 
407
- if not flow_paths_list.is_path_part_of_list(current_path):
408
- flow_paths_list.paths.append(copy.deepcopy(current_path))
406
+ self._go_over_steps(start_step, current_path, all_paths, visited_step_ids)
409
407
 
410
408
  structlogger.debug(
411
409
  "shared.core.flows.flow.extract_all_paths",
412
410
  comment="Extraction complete",
413
- number_of_paths=len(flow_paths_list.paths),
411
+ number_of_paths=len(all_paths.paths),
414
412
  flow_name=self.name,
415
413
  )
416
- return flow_paths_list
414
+ return all_paths
417
415
 
418
416
  def _go_over_steps(
419
417
  self,
420
- steps_to_go: Union[str, List[FlowStep]],
418
+ current_step: FlowStep,
421
419
  current_path: FlowPath,
422
- completed_paths: FlowPathsList,
423
- step_ids_visited: Set[str],
420
+ all_paths: FlowPathsList,
421
+ visited_step_ids: Set[str],
424
422
  ) -> None:
425
423
  """Processes the flow steps recursively.
426
424
 
427
- Either following direct step IDs or handling conditions, and adds complete
428
- paths to the collected_paths.
429
-
430
425
  Args:
431
- steps_to_go: Either a direct step ID or a list of steps to process.
426
+ current_step: The current step being processed.
432
427
  current_path: The current path being constructed.
433
- completed_paths: The list where completed paths are added.
434
- step_ids_visited: A set of step IDs that have been visited to avoid cycles.
428
+ all_paths: The list where completed paths are added.
429
+ visited_step_ids: A set of steps that have been visited to avoid cycles.
435
430
 
436
431
  Returns:
437
- None: This function modifies collected_paths in place by appending new paths
432
+ None: This function modifies all_paths in place by appending new paths
438
433
  as they are found.
439
434
  """
440
- # Case 1: If the steps_to_go is a custom_id string
441
- # This happens when a "next" of, for example, a IfFlowStepLink is targeting
442
- # a specific step by id
443
- if isinstance(steps_to_go, str):
444
- for i, step in enumerate(self.steps):
445
- # We don't need to check for 'id' as a link can only happen to a
446
- # custom id.
447
- if step.custom_id == steps_to_go:
448
- self._go_over_steps(
449
- self.steps[i:], current_path, completed_paths, step_ids_visited
450
- )
451
-
452
- # Case 2: If steps_to_go is a list of steps
453
- else:
454
- for i, step in enumerate(steps_to_go):
455
- # 1. Check if the step is relevant for testable_paths extraction.
456
- # We only create new path nodes for ActionFlowStep and
457
- # CollectInformationFlowStep because these are externally visible
458
- # changes in the assistant's behaviour (trackable in the e2e tests).
459
- # For other flow steps, we only follow their links.
460
- # We decided to ignore calls to other flows in our coverage analysis.
461
- if not isinstance(step, (CollectInformationFlowStep, ActionFlowStep)):
462
- self._handle_links(
463
- step.next.links,
464
- current_path,
465
- completed_paths,
466
- step_ids_visited,
467
- )
468
- continue
469
-
470
- # 2. Check if already visited this custom step id
471
- # in order to keep track of loops
472
- if step.custom_id is not None and step.custom_id in step_ids_visited:
473
- if not completed_paths.is_path_part_of_list(current_path):
474
- completed_paths.paths.append(copy.deepcopy(current_path))
475
- return # Stop traversing this path if we've revisited a step
476
- elif step.custom_id is not None:
477
- step_ids_visited.add(step.custom_id)
478
-
479
- # 3. Append step info to the path
480
- current_path.nodes.append(
481
- PathNode(
482
- flow=current_path.flow,
483
- step_id=step.id,
484
- lines=step.metadata["line_numbers"],
485
- )
435
+ # Check if the step is relevant for testable_paths extraction.
436
+ # We only create new path nodes for ActionFlowStep, CallFlowStep and
437
+ # CollectInformationFlowStep because these are externally visible
438
+ # changes in the assistant's behaviour (trackable in the e2e tests).
439
+ # For other flow steps, we only follow their links.
440
+ # We decided to ignore calls to other flows in our coverage analysis.
441
+ should_add_node = isinstance(
442
+ current_step, (CollectInformationFlowStep, ActionFlowStep, CallFlowStep)
443
+ )
444
+ if should_add_node:
445
+ # Add current step to the current path that is being constructed.
446
+ current_path.nodes.append(
447
+ PathNode(
448
+ flow=current_path.flow,
449
+ step_id=current_step.id,
450
+ lines=current_step.metadata["line_numbers"],
486
451
  )
452
+ )
487
453
 
488
- # 4. Check if 'END' branch
489
- if (
490
- len(step.next.links) == 1
491
- and isinstance(step.next.links[0], StaticFlowStepLink)
492
- and step.next.links[0].target == END_STEP
493
- ):
494
- if not completed_paths.is_path_part_of_list(current_path):
495
- completed_paths.paths.append(copy.deepcopy(current_path))
496
- return
497
- else:
498
- self._handle_links(
499
- step.next.links,
500
- current_path,
501
- completed_paths,
502
- step_ids_visited,
503
- )
454
+ if current_step.id in visited_step_ids or self.is_end_of_path(current_step):
455
+ # Found a cycle, or reached an end step, do not proceed further.
456
+ all_paths.paths.append(copy.deepcopy(current_path))
457
+ # Remove the last node from the path if it was added.
458
+ if should_add_node:
459
+ current_path.nodes.pop()
460
+ return
461
+
462
+ # Mark current step as visited in this path.
463
+ visited_step_ids.add(current_step.id)
464
+
465
+ # Iterate over all links of the current step.
466
+ for link in current_step.next.links:
467
+ self._handle_link(
468
+ current_path,
469
+ all_paths,
470
+ visited_step_ids,
471
+ link,
472
+ )
504
473
 
505
- def _handle_links(
474
+ # Backtrack the current step and remove it from the path.
475
+ visited_step_ids.remove(current_step.id)
476
+
477
+ # Remove the last node from the path if it was added.
478
+ if should_add_node:
479
+ current_path.nodes.pop()
480
+
481
+ def _handle_link(
506
482
  self,
507
- links: List[FlowStepLink],
508
- path: FlowPath,
509
- collected_paths: FlowPathsList,
510
- step_ids_visited: set,
483
+ current_path: FlowPath,
484
+ all_paths: FlowPathsList,
485
+ visited_step_ids: Set[str],
486
+ link: FlowStepLink,
511
487
  ) -> None:
512
- """Processes the next step in a flow.
513
-
514
- Potentially recursively calling itself to handle conditional paths and
515
- branching.
488
+ """Handles the next step in a flow.
516
489
 
517
490
  Args:
518
- links: Links listed in the "next" attribute.
519
- path: The current path taken in the flow.
520
- collected_paths: A list of paths collected so far.
521
- step_ids_visited: A set of step IDs that have already been visited
522
- to avoid loops.
491
+ current_path: The current path being constructed.
492
+ all_paths: The list where completed paths are added.
493
+ visited_step_ids: A set of steps that have been visited to avoid cycles.
494
+ link: The link to be followed.
523
495
 
524
496
  Returns:
525
- None: Modifies collected_paths in place by appending new paths
526
- as they are completed.
497
+ None: This function modifies all_paths in place by appending new paths
498
+ as they are found.
527
499
  """
528
- steps = self.steps
529
-
530
- for link in links:
531
- # Direct step id reference
532
- if isinstance(link, StaticFlowStepLink):
533
- # Find this id in the flow steps and restart from there
534
- for i, step in enumerate(steps):
535
- if step.id == link.target_step_id:
536
- self._go_over_steps(
537
- steps[i:],
538
- copy.deepcopy(path),
539
- collected_paths,
540
- copy.deepcopy(step_ids_visited),
541
- )
542
-
543
- # If conditions
544
- elif isinstance(link, (IfFlowStepLink, ElseFlowStepLink)):
545
- # Handling conditional paths
546
- target_steps: Union[str, List[FlowStep]]
547
- if isinstance(link.target_reference, FlowStepSequence):
548
- target_steps = link.target_reference.child_steps
549
- else:
550
- target_steps = link.target_reference
551
-
500
+ # StaticFlowStepLink is a direct link to the next step.
501
+ if isinstance(link, StaticFlowStepLink):
502
+ # Find the step by its id and continue the path.
503
+ if step := self._get_step_by_step_id(link.target_step_id):
552
504
  self._go_over_steps(
553
- target_steps,
554
- copy.deepcopy(path),
555
- collected_paths,
556
- copy.deepcopy(step_ids_visited),
505
+ step,
506
+ current_path,
507
+ all_paths,
508
+ visited_step_ids,
557
509
  )
510
+ return
511
+ # IfFlowStepLink and ElseFlowStepLink are conditional links.
512
+ elif isinstance(link, (IfFlowStepLink, ElseFlowStepLink)):
513
+ if isinstance(link.target_reference, FlowStepSequence):
514
+ # If the target is a FlowStepSequence, we need to go over all
515
+ # child steps of the sequence.
516
+ for child_step in link.target_reference.child_steps:
517
+ self._go_over_steps(
518
+ child_step,
519
+ current_path,
520
+ all_paths,
521
+ visited_step_ids,
522
+ )
523
+ return
524
+ else:
525
+ # Find the step by its id and continue the path.
526
+ if step := self._get_step_by_step_id(link.target_reference):
527
+ self._go_over_steps(
528
+ step,
529
+ current_path,
530
+ all_paths,
531
+ visited_step_ids,
532
+ )
533
+ return
534
+
535
+ def is_end_of_path(self, step: FlowStep) -> bool:
536
+ """Check if there is no path available from the current step."""
537
+ if (
538
+ len(step.next.links) == 1
539
+ and isinstance(step.next.links[0], StaticFlowStepLink)
540
+ and step.next.links[0].target == END_STEP
541
+ ):
542
+ return True
543
+ return False
544
+
545
+ def _get_step_by_step_id(
546
+ self,
547
+ step_id: Optional[str],
548
+ ) -> Optional[FlowStep]:
549
+ """Get a step by its id from a list of steps."""
550
+ for step in self.steps:
551
+ if step.id == step_id:
552
+ return step
553
+ return None
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.10.22"
3
+ __version__ = "3.10.23"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: rasa-pro
3
- Version: 3.10.22
3
+ Version: 3.10.23
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
@@ -559,7 +559,7 @@ rasa/shared/core/conversation.py,sha256=tw1fD2XB3gOdQjDI8hHo5TAAmE2JYNogQGWe3rE9
559
559
  rasa/shared/core/domain.py,sha256=_oemCcMY1SZgSrH-Yl9qv9n2vGNNDwdxlBxK3GZQaZQ,80517
560
560
  rasa/shared/core/events.py,sha256=38o-Zz3uQSKrYVfKw_Xr-EBvSusyXy3rQAvN25QzQJk,84875
561
561
  rasa/shared/core/flows/__init__.py,sha256=HszhIvEARpmyxABFc1MKYvj8oy04WiZW1xmCdToakbs,181
562
- rasa/shared/core/flows/flow.py,sha256=C8TxzxxEtZVrEMLUY57BNA8rEIwcYZaLtJ6pPYeBMRI,21242
562
+ rasa/shared/core/flows/flow.py,sha256=GbKSYvdQ3RN3NE8NZow4VCiWISfJrDy_tT9DeqLk4zg,20532
563
563
  rasa/shared/core/flows/flow_path.py,sha256=xstwahZBU5cfMY46mREA4NoOGlKLBRAqeP_mJ3UZqOI,2283
564
564
  rasa/shared/core/flows/flow_step.py,sha256=6hoVOMXryTKHgT7-p7jzTqH2r9QREmy_6d6bX2OyxI0,4550
565
565
  rasa/shared/core/flows/flow_step_links.py,sha256=zMZV_9rWVjEa8kHIFSIbXCWA1qaUvp8r4uSCK_NsKKs,10548
@@ -727,9 +727,9 @@ rasa/utils/train_utils.py,sha256=f1NWpp5y6al0dzoQyyio4hc4Nf73DRoRSHDzEK6-C4E,212
727
727
  rasa/utils/url_tools.py,sha256=JQcHL2aLqLHu82k7_d9imUoETCm2bmlHaDpOJ-dKqBc,1218
728
728
  rasa/utils/yaml.py,sha256=KjbZq5C94ZP7Jdsw8bYYF7HASI6K4-C_kdHfrnPLpSI,2000
729
729
  rasa/validator.py,sha256=AsFJ8e1zWHW-hnH_IB3SGBBl68vstKPrrqbAydgjVhQ,63149
730
- rasa/version.py,sha256=7WOmVknYopPEss4c04bmXtfiEML3B7O8MZxRyZSPUQA,118
731
- rasa_pro-3.10.22.dist-info/METADATA,sha256=7SgvI8XLWi_WLwZInMqQGxocS5m_echgfQFXvD2c1A0,10856
732
- rasa_pro-3.10.22.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
733
- rasa_pro-3.10.22.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
734
- rasa_pro-3.10.22.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
735
- rasa_pro-3.10.22.dist-info/RECORD,,
730
+ rasa/version.py,sha256=gffVz2yUxqizelkQ9ZVOh04vLl7KUjaaV5fVG-LsPfg,118
731
+ rasa_pro-3.10.23.dist-info/METADATA,sha256=wgW8uzyRaeMkrriCmAGI6W9pMIe63dDkU4qGNAAZo0g,10856
732
+ rasa_pro-3.10.23.dist-info/NOTICE,sha256=7HlBoMHJY9CL2GlYSfTQ-PZsVmLmVkYmMiPlTjhuCqA,218
733
+ rasa_pro-3.10.23.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
734
+ rasa_pro-3.10.23.dist-info/entry_points.txt,sha256=ckJ2SfEyTPgBqj_I6vm_tqY9dZF_LAPJZA335Xp0Q9U,43
735
+ rasa_pro-3.10.23.dist-info/RECORD,,