class_docstr: Manager for multiple ProjectionInterpreter instances.
  
  Presents a standard "Interpreter" interface so that client code can treat
  this as an ordinary stateless component.
  
  The config is used to uniquely identify the projection instance, and a new
  instance is created and fit if not found.
  
  Config must contain the following fields:
  - field_name: name of embedding field (in model output)
  - (optional) proj_kw: config for the underlying ProjectorModel
  
  We also recommend including the model name and dataset name in the key, but
  this is not explicitly enforced.
class_docstr_tok: ["Manager","for","multiple","ProjectionInterpreter","instances",".","Presents","a","standard","``","Interpreter","''","interface","so","that","client","code","can","treat","this","as","an","ordinary","stateless","component",".","The","config","is","used","to","uniquely","identify","the","projection","instance",",","and","a","new","instance","is","created","and","fit","if","not","found",".","Config","must","contain","the","following","fields",":","-","field_name",":","name","of","embedding","field","(","in","model","output",")","-","(","optional",")","proj_kw",":","config","for","the","underlying","ProjectorModel","We","also","recommend","including","the","model","name","and","dataset","name","in","the","key",",","but","this","is","not","explicitly","enforced","."]
code: def run(
      self,
      inputs: list[JsonDict],
      model: lit_model.Model,
      dataset: lit_dataset.Dataset,
      model_outputs: Optional[list[JsonDict]] = None,
      config: Optional[JsonDict] = None,
  ):
      # UMAP code is not threadsafe and will throw strange 'index-out-of-bounds'
      # errors if multiple instances are accessed concurrently.
      with self._lock:
          instance_key = _key_from_dict(config)
          logging.info(
              "Projection request: instance key: %s", instance_key
          )
          # Fit a new instance if necessary
          if instance_key not in self._instances:
              self._instances[instance_key] = self._train_instance(
                  model, dataset, config, name=str(instance_key)
              )
  
          proj_instance = self._instances[instance_key]
          # If projector was just trained, points should be cached.
          return proj_instance.run(
              inputs, model, dataset, model_outputs, config
          )
  
imports: from collections.abc import Hashable, Sequence
  import threading
  from typing import Optional
  from absl import logging
  from lit_nlp.api import components
  from lit_nlp.api import dataset
  from lit_nlp.api import model
  from lit_nlp.api import types
  from lit_nlp.lib import caching
label_desc: Use image node_id 3 for calling the ProjectionManager obj's underlying member method code with example usage: obj.run(inputs, model, dataset, model_outputs, config) and returns: proj_instance