Repository: facebookresearch/ParlAI

Issue:
QuickStart instructions yield AttributeError: 'MemnnAgent' object has no attribute 'vocab_candidate_encs'
**Bug description**

When going through the [ParlAI quickstart](https://parl.ai/docs/tutorial_quick.html#view-a-task-train-a-model
), I get the following error:
```python
Traceback (most recent call last):
  File "examples/display_model.py", line 16, in <module>
    display_model(opt)
  File "/root/ParlAI/parlai/scripts/display_model.py", line 44, in display_model
    world.parley()
  File "/root/ParlAI/parlai/core/worlds.py", line 274, in parley
    acts[1] = agents[1].act()
  File "/root/ParlAI/parlai/core/torch_agent.py", line 1674, in act
    return self.batch_act([self.observation])[0]
  File "/root/ParlAI/parlai/core/torch_agent.py", line 1703, in batch_act
    output = self.eval_step(batch)
  File "/root/ParlAI/parlai/core/torch_ranker_agent.py", line 383, in eval_step
    cand_encs = self.vocab_candidate_encs
AttributeError: 'MemnnAgent' object has no attribute 'vocab_candidate_encs'
```

when running:
```bash
# display predictions for model save at specified file on bAbI task 1
python examples/display_model.py -t babi:task10k:1 -mf /tmp/babi_memnn -ecands vocab

```


Discussion:
This looks like a TRA issue. Need review.

Resolving patch:
diff --git a/parlai/agents/transformer/polyencoder.py b/parlai/agents/transformer/polyencoder.py
--- a/parlai/agents/transformer/polyencoder.py
+++ b/parlai/agents/transformer/polyencoder.py
@@ -115,12 +115,12 @@ def vectorize_fixed_candidates(self, *args, **kwargs):
         kwargs['add_end'] = True
         return super().vectorize_fixed_candidates(*args, **kwargs)
 
-    def _make_candidate_encs(self, vecs, path):
+    def _make_candidate_encs(self, vecs):
         """ (used in interactive mode only) The polyencoder module expects
             cand vecs to be 3D while torch_ranker_agent expects it to be 2D.
             This requires a little adjustment
         """
-        rep = super()._make_candidate_encs(vecs, path)
+        rep = super()._make_candidate_encs(vecs)
         return rep.transpose(0, 1).contiguous()
 
     def encode_candidates(self, padded_cands):
diff --git a/parlai/core/torch_ranker_agent.py b/parlai/core/torch_ranker_agent.py
--- a/parlai/core/torch_ranker_agent.py
+++ b/parlai/core/torch_ranker_agent.py
@@ -701,6 +701,7 @@ def share(self):
         shared['fixed_candidate_encs'] = self.fixed_candidate_encs
         shared['vocab_candidates'] = self.vocab_candidates
         shared['vocab_candidate_vecs'] = self.vocab_candidate_vecs
+        shared['vocab_candidate_encs'] = self.vocab_candidate_encs
         shared['optimizer'] = self.optimizer
         return shared
 
@@ -745,6 +746,7 @@ def set_vocab_candidates(self, shared):
         if shared:
             self.vocab_candidates = shared['vocab_candidates']
             self.vocab_candidate_vecs = shared['vocab_candidate_vecs']
+            self.vocab_candidate_encs = shared['vocab_candidate_encs']
         else:
             if 'vocab' in (self.opt['candidates'], self.opt['eval_candidates']):
                 cands = []
@@ -760,9 +762,24 @@ def set_vocab_candidates(self, shared):
                 )
                 if self.use_cuda:
                     self.vocab_candidate_vecs = self.vocab_candidate_vecs.cuda()
+
+                if self.encode_candidate_vecs:
+                    # encode vocab candidate vecs
+                    self.vocab_candidate_encs = self._make_candidate_encs(
+                        self.vocab_candidate_vecs
+                    )
+                    if self.use_cuda:
+                        self.vocab_candidate_encs = self.vocab_candidate_encs.cuda()
+                    if self.fp16:
+                        self.vocab_candidate_encs = self.vocab_candidate_encs.half()
+                    else:
+                        self.vocab_candidate_encs = self.vocab_candidate_encs.float()
+                else:
+                    self.vocab_candidate_encs = None
             else:
                 self.vocab_candidates = None
                 self.vocab_candidate_vecs = None
+                self.vocab_candidate_encs = None
 
     def set_fixed_candidates(self, shared):
         """
@@ -824,9 +841,7 @@ def set_fixed_candidates(self, shared):
                     if setting == 'reuse' and os.path.isfile(enc_path):
                         encs = self.load_candidates(enc_path, cand_type='encodings')
                     else:
-                        encs = self._make_candidate_encs(
-                            self.fixed_candidate_vecs, path=enc_path
-                        )
+                        encs = self._make_candidate_encs(self.fixed_candidate_vecs)
                         self._save_candidates(
                             encs, path=enc_path, cand_type='encodings'
                         )
@@ -885,7 +900,7 @@ def encode_candidates(self, padded_cands):
             '--encode-candidate-vecs True.'
         )
 
-    def _make_candidate_encs(self, vecs, path):
+    def _make_candidate_encs(self, vecs):
         """
         Encode candidates from candidate vectors.
 


Test patch: