class_docstr: Builds and/or loads a dictionary.
  
  The dictionary provides access to the frequency of each token, functions to
  translate sentences from tokens to their vectors (list of ints, each int is the
  index of a token in the dictionary) and back from vectors to tokenized text.
class_docstr_tok: ["Builds","and\/or","loads","a","dictionary",".","The","dictionary","provides","access","to","the","frequency","of","each","token",",","functions","to","translate","sentences","from","tokens","to","their","vectors","(","list","of","ints",",","each","int","is","the","index","of","a","token","in","the","dictionary",")","and","back","from","vectors","to","tokenized","text","."]
docstr: Save dictionary to file.
  
  Format is 'token<TAB>count' for every token in the dictionary, sorted
  by count with the most frequent words first.
  
  If ``append`` (default ``False``) is set to ``True``, appends instead of
  overwriting.
  
  If ``sort`` (default ``True``), then first sort the dictionary before saving.
code: def save(self, filename=None, append=False, sort=True):
      """
      Save dictionary to file.
  
      Format is 'token<TAB>count' for every token in the dictionary, sorted
      by count with the most frequent words first.
  
      If ``append`` (default ``False``) is set to ``True``, appends instead of
      overwriting.
  
      If ``sort`` (default ``True``), then first sort the dictionary before saving.
      """
      filename = self.opt["dict_file"] if filename is None else filename
      make_dir(os.path.dirname(filename))
  
      if self.tokenizer in [
          "bpe",
          "gpt2",
          "bytelevelbpe",
          "slow_bytelevel_bpe",
      ]:
          needs_removal = self.bpe.finalize(
              self.freq,
              num_symbols=self.maxtokens,
              minfreq=self.minfreq,
          )
          if needs_removal:
              self._remove_non_bpe()
          elif filename != self.opt.get("dict_file"):
              # need to copy over the old codecs file
              self.bpe.copy_codecs_file(filename + ".codecs")
          if sort and self.bpe.should_sort():
              self.sort(trim=False)
      elif sort:
          self.sort(trim=True)
  
      logging.info(f"Saving dictionary to {filename}")
  
      mode = "a" if append else "w"
      with PathManager.open(filename, mode, encoding="utf-8") as write:
          for i in self.ind2tok.keys():
              tok = self.ind2tok[i]
              cnt = self.freq[tok]
              write.write(
                  "{tok}\t{cnt}\n".format(tok=escape(tok), cnt=cnt)
              )
  
      # save opt file
      with PathManager.open(
          filename + ".opt", "w", encoding="utf-8"
      ) as handle:
          json.dump(self.opt, handle, indent=4)
      # save the byte level bpe model file as well
      if (
          self.tokenizer == "bytelevelbpe"
          or self.tokenizer == "slow_bytelevel_bpe"
      ):
          # This saves filename-vocab.json and filename-merges.txt as
          # hugging face tokenizer does
          self.bpe.save(
              os.path.dirname(filename), os.path.basename(filename)
          )
  
imports: from typing import Optional
  from parlai.core.params import ParlaiParser
  from parlai.core.opt import Opt
  from parlai.core.build_data import modelzoo_path
  from parlai.utils.bpe import bpe_factory, BPEHelper
  from .agents import Agent
  from .build_data import make_dir
  from collections import defaultdict
  import copy
  import numpy
  import os
  import json
  import re
  import parlai.utils.logging
  from parlai.utils.io import PathManager
  from typing import List
  import enum
label_desc: Use image node_id 28 for calling the DictionaryAgent obj's underlying member method code with example usage: obj.save(filename, append, sort) without return types