class_docstr: Wrapper over RecSim for simulating (Personalized) VM Tuning.
  The state is the same as for RecSim (user feature + candidate features).
  There are num_weights VM weights to tune, and so action space is a vector
  of length num_weights.
  OraclePVM hides num_weights number of
  (1) score_fns (akin to VM models), that take in
      user + candidate_i feature and produces a score for candidate_i.
  (2) ground_truth_weights, that are used to produce "ground truth", a.k.a.
      "Oracle", rankings.
  Reward is the Kendall-Tau between ground truth and the ranking created from the
  weights given by action. If the rankings match exactly, the reward is boosted to 3.
  NOTE: This environment only tests if the Agent can learn the hidden ground
  truth weights, which may be far from optimal (in terms of RecSim's rewards,
  which we're ignoring). This is easier for unit tests, but in the real world
  we will be trying to learn the optimal weights, and the reward signal would
  reflect that.
  
  TODO: made environment easier to learn from by not using RecSim.
class_docstr_tok: ["Wrapper","over","RecSim","for","simulating","(","Personalized",")","VM","Tuning",".","The","state","is","the","same","as","for","RecSim","(","user","feature","+","candidate","features",")",".","There","are","num_weights","VM","weights","to","tune",",","and","so","action","space","is","a","vector","of","length","num_weights",".","OraclePVM","hides","num_weights","number","of","(","1",")","score_fns","(","akin","to","VM","models",")",",","that","take","in","user","+","candidate_i","feature","and","produces","a","score","for","candidate_i",".","(","2",")","ground_truth_weights",",","that","are","used","to","produce","``","ground","truth","''",",","a.k.a",".","``","Oracle","''",",","rankings",".","Reward","is","the","Kendall-Tau","between","ground","truth","and","the","ranking","created","from","the","weights","given","by","action",".","If","the","rankings","match","exactly",",","the","reward","is","boosted","to","3",".","NOTE",":","This","environment","only","tests","if","the","Agent","can","learn","the","hidden","ground","truth","weights",",","which","may","be","far","from","optimal","(","in","terms","of","RecSim","'s","rewards",",","which","we","'re","ignoring",")",".","This","is","easier","for","unit","tests",",","but","in","the","real","world","we","will","be","trying","to","learn","the","optimal","weights",",","and","the","reward","signal","would","reflect","that",".","TODO",":","made","environment","easier","to","learn","from","by","not","using","RecSim","."]
code: def _get_scores(
      self, user_feat: np.ndarray, doc_feats: Dict[str, np.ndarray]
  ) -> np.ndarray:
      # num_docs x num_scores where i,j coordinate is jth score for ith doc
      scores = np.array(
          [
              [
                  score_fn(user_feat, doc_feat)
                  for score_fn in self.score_fns
              ]
              for _k, doc_feat in doc_feats.items()
          ]
      )
      return scores
  
imports: import logging
  from collections import OrderedDict
  from typing import Callable, Dict, List
  import gym
  import numpy
  import reagent.core.types
  import torch
  from reagent.core.dataclasses import dataclass
  from reagent.gym.envs import RecSim
  from reagent.gym.preprocessors.default_preprocessors import RecsimObsPreprocessor
  from scipy import stats
label_desc: Use image node_id 7 for calling the OraclePVM obj's underlying member method code with example usage: obj._get_scores(user_feat, doc_feats) and returns: scores