class_docstr: Trains a model using a graph schema.
class_docstr_tok: ["Trains","a","model","using","a","graph","schema","."]
docstr: Recursively walks backwards though a graph checking the status of each node.
  
  If node has a fingerprint key hit then we check if there is a cached output.
  If there is a cached output we will replace the node with a
  `PrecomputedValueProvider` and remove all its dependencies (`.needs`). If
  there is not a fingerprint key hit, or there is no cached output, the node is
  left untouched and will be executed again next run unless it is no longer the
  ancestor of a target node.
  
  Args:
      schema: The graph we are currently walking.
      current_node_name: The current node on the walk.
      fingerprint_run_outputs: The fingerprint statuses of every node as a mapping
          from node name to status.
docstr_tok: ["Recursively","walks","backwards","though","a","graph","checking","the","status","of","each","node",".","If","node","has","a","fingerprint","key","hit","then","we","check","if","there","is","a","cached","output",".","If","there","is","a","cached","output","we","will","replace","the","node","with","a","`","PrecomputedValueProvider","`","and","remove","all","its","dependencies","(","`",".needs","`",")",".","If","there","is","not","a","fingerprint","key","hit",",","or","there","is","no","cached","output",",","the","node","is","left","untouched","and","will","be","executed","again","next","run","unless","it","is","no","longer","the","ancestor","of","a","target","node",".","Args",":","schema",":","The","graph","we","are","currently","walking",".","current_node_name",":","The","current","node","on","the","walk",".","fingerprint_run_outputs",":","The","fingerprint","statuses","of","every","node","as","a","mapping","from","node","name","to","status","."]
code: def _walk_and_prune(
      self,
      schema: GraphSchema,
      current_node_name: Text,
      fingerprint_run_outputs: Dict[
          Text, Union[FingerprintStatus, Any]
      ],
  ) -> None:
      """Recursively walks backwards though a graph checking the status of each node.
  
      If node has a fingerprint key hit then we check if there is a cached output.
      If there is a cached output we will replace the node with a
      `PrecomputedValueProvider` and remove all its dependencies (`.needs`). If
      there is not a fingerprint key hit, or there is no cached output, the node is
      left untouched and will be executed again next run unless it is no longer the
      ancestor of a target node.
  
      Args:
          schema: The graph we are currently walking.
          current_node_name: The current node on the walk.
          fingerprint_run_outputs: The fingerprint statuses of every node as a mapping
              from node name to status.
      """
      fingerprint_run_output = fingerprint_run_outputs[
          current_node_name
      ]
      node = schema.nodes[current_node_name]
  
      # If we have replaced this node with a `PrecomputedValueProvider` we have
      # already visited this node. A `PrecomputedValueProvider` is updated to have
      # no parent nodes, so
      # we can end the walk here.
      if node.uses == PrecomputedValueProvider:
          return
  
      # If the output was a `FingerprintStatus` we must check the cache and status.
      if isinstance(fingerprint_run_output, FingerprintStatus):
          # If there is a fingerprint key hit we can potentially use a cached output.
          if fingerprint_run_output.is_hit:
              output_result = self._cache.get_cached_result(
                  output_fingerprint_key=fingerprint_run_output.output_fingerprint,
                  node_name=current_node_name,
                  model_storage=self._model_storage,
              )
              if output_result:
                  logger.debug(
                      f"Updating '{current_node_name}' to use a "
                      f"'{PrecomputedValueProvider.__name__}'."
                  )
                  PrecomputedValueProvider.replace_schema_node(
                      node, output_result
                  )
                  # We remove all parent dependencies as the cached output value will
                  # be used.
                  node.needs = {}
              else:
                  # If there is no cached output the node must be re-run if it ends
                  # up as an ancestor of a target node.
                  fingerprint_run_output.is_hit = False
  
      # Else the node was an input node and the output is the actual node's output.
      else:
          # As fingerprint_run_output is just the node's output there is no need to
          # execute the node again. We can just return it from a
          # `PrecomputedValueProvider`.
          PrecomputedValueProvider.replace_schema_node(
              node, fingerprint_run_output
          )
          node.needs = {}
  
      # Continue walking for every parent node.
      for parent_node_name in node.needs.values():
          self._walk_and_prune(
              schema, parent_node_name, fingerprint_run_outputs
          )
  
file_path: rasa/rasa/engine/training/graph_trainer.py
imports: import copy
  import logging
  from pathlib import Path
  from typing import Any, Dict, Text, Type, Union
  from rasa.engine.caching import TrainingCache
  from rasa.engine.graph import ExecutionContext, GraphSchema, GraphModelConfiguration
  from rasa.engine.constants import PLACEHOLDER_IMPORTER
  from rasa.engine.runner.interface import GraphRunner
  from rasa.engine.storage.storage import ModelStorage, ModelMetadata
  from rasa.engine.training.components import PrecomputedValueProvider, FingerprintComponent, FingerprintStatus
  from rasa.engine.training.hooks import TrainingHook, LoggingHook
  from rasa.shared.importers.importer import TrainingDataImporter
label_desc: Use image node_id 6 for calling the GraphTrainer obj's underlying member method code with example usage: obj._walk_and_prune(schema, current_node_name, fingerprint_run_outputs) without return types