class_docstr: Components orchestration engine.
  
  Builds a graph of components and orchestrates their execution according to the execution graph.
class_docstr_tok: ["Components","orchestration","engine",".","Builds","a","graph","of","components","and","orchestrates","their","execution","according","to","the","execution","graph","."]
docstr: Creates a Pipeline instance from a dictionary.
  A sample `data` dictionary could be formatted like so:
  ```
  {
      "metadata": {"test": "test"},
      "max_loops_allowed": 100,
      "components": {
          "add_two": {
              "type": "AddFixedValue",
              "init_parameters": {"add": 2},
          },
          "add_default": {
              "type": "AddFixedValue",
              "init_parameters": {"add": 1},
          },
          "double": {
              "type": "Double",
          },
      },
      "connections": [
          {"sender": "add_two.result", "receiver": "double.value"},
          {"sender": "double.value", "receiver": "add_default.value"},
      ],
  }
  ```
  
  Supported kwargs:
  `components`: a dictionary of {name: instance} to reuse instances of components instead of creating new ones.
docstr_tok: ["Creates","a","Pipeline","instance","from","a","dictionary",".","A","sample","`","data","`","dictionary","could","be","formatted","like","so",":","``","`","{","``","metadata","''",":","{","``","test","''",":","``","test","''","}",",","``","max_loops_allowed","''",":","100",",","``","components","''",":","{","``","add_two","''",":","{","``","type","''",":","``","AddFixedValue","''",",","``","init_parameters","''",":","{","``","add","''",":","2","}",",","}",",","``","add_default","''",":","{","``","type","''",":","``","AddFixedValue","''",",","``","init_parameters","''",":","{","``","add","''",":","1","}",",","}",",","``","double","''",":","{","``","type","''",":","``","Double","''",",","}",",","}",",","``","connections","''",":","[","{","``","sender","''",":","``","add_two.result","''",",","``","receiver","''",":","``","double.value","''","}",",","{","``","sender","''",":","``","double.value","''",",","``","receiver","''",":","``","add_default.value","''","}",",","]",",","}","``","`","Supported","kwargs",":","`","components","`",":","a","dictionary","of","{","name",":","instance","}","to","reuse","instances","of","components","instead","of","creating","new","ones","."]
code: def from_dict(cls: Type[T], data: Dict[str, Any], **kwargs) -> T:
      """
      Creates a Pipeline instance from a dictionary.
      A sample `data` dictionary could be formatted like so:
      ```
      {
          "metadata": {"test": "test"},
          "max_loops_allowed": 100,
          "components": {
              "add_two": {
                  "type": "AddFixedValue",
                  "init_parameters": {"add": 2},
              },
              "add_default": {
                  "type": "AddFixedValue",
                  "init_parameters": {"add": 1},
              },
              "double": {
                  "type": "Double",
              },
          },
          "connections": [
              {"sender": "add_two.result", "receiver": "double.value"},
              {"sender": "double.value", "receiver": "add_default.value"},
          ],
      }
      ```
  
      Supported kwargs:
      `components`: a dictionary of {name: instance} to reuse instances of components instead of creating new ones.
      """
      metadata = data.get("metadata", {})
      max_loops_allowed = data.get("max_loops_allowed", 100)
      debug_path = Path(data.get("debug_path", ".canals_debug/"))
      pipe = cls(
          metadata=metadata,
          max_loops_allowed=max_loops_allowed,
          debug_path=debug_path,
      )
      components_to_reuse = kwargs.get("components", {})
      for name, component_data in data.get("components", {}).items():
          if name in components_to_reuse:
              # Reuse an instance
              instance = components_to_reuse[name]
          else:
              if "type" not in component_data:
                  raise PipelineError(
                      f"Missing 'type' in component '{name}'"
                  )
  
              if component_data["type"] not in component.registry:
                  try:
                      # Import the module first...
                      module, _ = component_data["type"].rsplit(".", 1)
                      logger.debug("Trying to import %s", module)
                      importlib.import_module(module)
                      # ...then try again
                      if (
                          component_data["type"]
                          not in component.registry
                      ):
                          raise PipelineError(
                              f"Successfully imported module {module} but can't find it in the component registry."
                              "This is unexpected and most likely a bug."
                          )
                  except (ImportError, PipelineError) as e:
                      raise PipelineError(
                          f"Component '{component_data['type']}' not imported."
                      ) from e
  
              # Create a new one
              component_class = component.registry[
                  component_data["type"]
              ]
              instance = component_from_dict(
                  component_class, component_data
              )
          pipe.add_component(name=name, instance=instance)
  
      for connection in data.get("connections", []):
          if "sender" not in connection:
              raise PipelineError(
                  f"Missing sender in connection: {connection}"
              )
          if "receiver" not in connection:
              raise PipelineError(
                  f"Missing receiver in connection: {connection}"
              )
          pipe.connect(
              connect_from=connection["sender"],
              connect_to=connection["receiver"],
          )
  
      return pipe
  
imports: from typing import Optional, Any, Dict, List, Union, TypeVar, Type, Set
  import os
  import json
  import datetime
  import logging
  import importlib
  from pathlib import Path
  from copy import deepcopy
  from collections import defaultdict
  import networkx
  from haystack.core.component import component, Component, InputSocket, OutputSocket
  from haystack.core.errors import PipelineError, PipelineConnectError, PipelineMaxLoops, PipelineRuntimeError, PipelineValidationError
  from haystack.core.pipeline.descriptions import find_pipeline_outputs
  from haystack.core.pipeline.draw.draw import _draw, RenderingEngines
  from haystack.core.pipeline.validation import validate_pipeline_input, find_pipeline_inputs
  from haystack.core.component.connection import Connection, parse_connect_string
  from haystack.core.type_utils import _type_name
  from haystack.core.serialization import component_to_dict, component_from_dict
label_desc: Use image node_id 4 for calling the Pipeline obj's underlying member method code with example usage: obj.from_dict(cls, data) and returns: pipe