code: def postprocess_doc(doc, postprocessor, orig_text=None):
      """Applies a postprocessor on the doc"""
  
      # get a list of all the words in the "draft" document to pass to the postprocessor
      # the words array looks like [["words, "words", "words"], ["words, ("i_am_a_mwt", True), "I_am_not"]]
      # and the postprocessor is expected to return in the same format
      words = [
          [
              (
                  (word["text"], True)
                  if word.get("misc") == "MWT=Yes"
                  else word["text"]
              )
              for word in sentence
          ]
          for sentence in doc
      ]
      if not orig_text:
          raw_text = "".join(
              "".join(i) for i in all_raw
          )  # template to compare the stitched text against
      else:
          raw_text = orig_text
  
      # perform correction with the postprocessor
      postprocessor_return = postprocessor(words)
  
      # collect the words and MWTs seperately
      corrected_words = []
      corrected_mwts = []
      corrected_expansions = []
  
      # for each word, if its just a string (without the ("word", mwt_bool) format)
      # we default that the word is not a MWT.
      for sent in postprocessor_return:
          sent_words = []
          sent_mwts = []
          sent_expansions = []
          for word in sent:
              if isinstance(word, str):
                  sent_words.append(word)
                  sent_mwts.append(False)
                  sent_expansions.append(None)
              else:
                  if isinstance(word[1], bool):
                      sent_words.append(word[0])
                      sent_mwts.append(word[1])
                      sent_expansions.append(None)
                  else:
                      sent_words.append(word[0])
                      sent_mwts.append(True)
                      # expansions are marked in a space-seperated list, which
                      # `stanza.common.doc.set_mwt_expansions` reads and splits again
                      # by splitting by spaces. Therefore, to serialize the users' supplied MWT
                      # information, we join them by spaces to be split later by
                      # `set_mwt_expansions`.
                      sent_expansions.append(" ".join(word[1]))
          corrected_words.append(sent_words)
          corrected_mwts.append(sent_mwts)
          corrected_expansions.append(sent_expansions)
  
      # check postprocessor output
      token_lens = [len(i) for i in corrected_words]
      mwt_lens = [len(i) for i in corrected_mwts]
      assert token_lens == mwt_lens, (
          "Postprocessor returned token and MWT lists of different length! Token list lengths %s, MWT list lengths %s"
          % (token_lens, mwt_lens)
      )
  
      # reassemble document. offsets and oov shouldn't change
      doc = reassemble_doc_from_tokens(
          corrected_words,
          corrected_mwts,
          corrected_expansions,
          raw_text,
      )
  
      return doc
  
imports: from collections import Counter
  from copy import copy
  import json
  import numpy
  import re
  import logging
  import os
  from torch.utils.data import DataLoader
  import stanza.utils.default_paths
  from stanza.models.common.utils import ud_scores, harmonic_mean
  from stanza.models.common.doc import Document
  from stanza.utils.conll import CoNLL
  from stanza.models.common.doc import *
  from stanza.models.tokenization.data import SortedDataset
label_desc: Use image node_id 10 for calling a global function with example usage: postprocess_doc(doc, postprocessor, orig_text) and returns: doc