code: def preprocess_prompt(
      self, history: List[Dialogue], max_new_tokens: int
  ) -> str:
      if self.context_len is None:
          self.context_len = len(
              self.tokenizer(self.context)["input_ids"]
          )
      if self.dialogue_placeholder_len is None:
          self.dialogue_placeholder_len = len(
              self.tokenizer(
                  _format_dialogue(""), add_special_tokens=False
              )["input_ids"]
          )
      prompt = self.context
      # the last dialogue must be in the prompt
      last_dialogue = history.pop()
      # the response of the last dialogue is empty
      assert last_dialogue.response == ""
      if (
          len(
              self.tokenizer(
                  _format_dialogue(last_dialogue.instruction),
                  add_special_tokens=False,
              )["input_ids"]
          )
          + max_new_tokens
          + self.context_len
          >= self.max_len
      ):
          # to avoid truncate placeholder, apply truncate to the original instruction
          instruction_truncated = self.tokenizer(
              last_dialogue.instruction,
              add_special_tokens=False,
              truncation=True,
              max_length=(
                  self.max_len
                  - max_new_tokens
                  - self.context_len
                  - self.dialogue_placeholder_len
              ),
          )["input_ids"]
          instruction_truncated = self.tokenizer.decode(
              instruction_truncated
          ).lstrip()
          prompt += _format_dialogue(instruction_truncated)
          return prompt
  
      res_len = (
          self.max_len
          - max_new_tokens
          - len(self.tokenizer(prompt)["input_ids"])
      )
  
      rows = []
      for dialogue in history[::-1]:
          text = _format_dialogue(
              dialogue.instruction, dialogue.response
          )
          cur_len = len(
              self.tokenizer(text, add_special_tokens=False)[
                  "input_ids"
              ]
          )
          if res_len - cur_len < 0:
              break
          res_len -= cur_len
          rows.insert(0, text)
      prompt += "".join(rows) + _format_dialogue(
          last_dialogue.instruction
      )
      return prompt
  
imports: import json
  import re
  from threading import Lock
  from typing import Any, Callable, Generator, List, Optional
  import jieba
  import torch
  import torch.distributed
  import torch.nn
  from pydantic import BaseModel, Field
label_desc: Use image node_id 2 for calling the ChatPromptProcessor obj's underlying member method code with example usage: obj.preprocess_prompt(history, max_new_tokens) and returns: prompt, prompt