code: def eval_model(args):
      # Model
      disable_torch_init()
      model_path = os.path.expanduser(args.model_path)
      model_name = get_model_name_from_path(model_path)
      (
          tokenizer,
          model,
          image_processor,
          context_len,
      ) = load_pretrained_model(model_path, args.model_base, model_name)
  
      questions = [
          json.loads(q)
          for q in open(os.path.expanduser(args.question_file), "r")
      ]
      questions = get_chunk(questions, args.num_chunks, args.chunk_idx)
      answers_file = os.path.expanduser(args.answers_file)
      os.makedirs(os.path.dirname(answers_file), exist_ok=True)
      ans_file = open(answers_file, "w")
  
      if (
          "plain" in model_name
          and "finetune" not in model_name.lower()
          and "mmtag" not in args.conv_mode
      ):
          args.conv_mode = args.conv_mode + "_mmtag"
          print(
              f"It seems that this is a plain model, but it is not using a mmtag prompt, auto switching to {args.conv_mode}."
          )
  
      data_loader = create_data_loader(
          questions,
          args.image_folder,
          tokenizer,
          image_processor,
          model.config,
      )
  
      for (input_ids, image_tensor, prompt), line in tqdm(
          zip(data_loader, questions), total=len(questions)
      ):
          idx = line["question_id"]
          cur_prompt = line["text"]
          stop_str = (
              conv_templates[args.conv_mode].sep
              if conv_templates[args.conv_mode].sep_style
              != SeparatorStyle.TWO
              else conv_templates[args.conv_mode].sep2
          )
          input_ids = input_ids.to(device="cuda", non_blocking=True)
  
          qs_highlighted_parts = []
          highlighted_mask, tokens = txt_highlight_mask(
              tokenizer, prompt[0], qs_highlighted_parts
          )
  
          highlighted_mask = [
              0
          ] + highlighted_mask  # add a start token placeholder
  
          masked_img_token_map = [1] * 576
  
          # extend masked token map to the end of input_ids
          id_len = input_ids.shape[1]
  
          image_token_indices = torch.where(
              input_ids == IMAGE_TOKEN_INDEX
          )[1]
          image_token_start = image_token_indices[0]
          masked_token_map = (
              highlighted_mask[:image_token_start]
              + masked_img_token_map
              + highlighted_mask[image_token_start + 1 :]
          )
  
          # change to long tensor:
          masked_token_map = torch.LongTensor(masked_token_map).cuda()
  
          # use the batched cfg version for input_ids and images
          input_ids = input_ids.repeat(2, 1)
          image_tensor = image_tensor.repeat(2, 1, 1, 1)
  
          llava_modify_inf(model)
  
          with torch.inference_mode():
              output_ids = model.generate(
                  input_ids,
                  images=image_tensor.to(
                      dtype=torch.float16,
                      device="cuda",
                      non_blocking=True,
                  ),
                  masked_token_map=masked_token_map,
                  perturb_weight=args.perturb_weight,
                  attention_weight=args.attn,
                  do_sample=True if args.temperature > 0 else False,
                  temperature=args.temperature,
                  top_p=args.top_p,
                  num_beams=args.num_beams,
                  max_new_tokens=128,
                  logits_processor=[
                      ProbCFGLogitsProcessor(
                          guidance_scale=args.cfg, use_log=False
                      )
                  ],
                  use_cache=True,
              )
  
          input_token_len = input_ids.shape[1]
          n_diff_input_output = (
              (input_ids != output_ids[:, :input_token_len])
              .sum()
              .item()
          )
          if n_diff_input_output > 0:
              print(
                  f"[Warning] {n_diff_input_output} output_ids are not the same as the input_ids"
              )
          outputs = tokenizer.batch_decode(
              output_ids[:, input_token_len:], skip_special_tokens=True
          )[0]
          outputs = outputs.strip()
          if outputs.endswith(stop_str):
              outputs = outputs[: -len(stop_str)]
          outputs = outputs.strip()
  
          ans_id = shortuuid.uuid()
          ans_file.write(
              json.dumps(
                  {
                      "question_id": idx,
                      "prompt": cur_prompt,
                      "text": outputs,
                      "answer_id": ans_id,
                      "model_id": model_name,
                      "metadata": {},
                  }
              )
              + "\n"
          )
          ans_file.flush()
          # reset model
          model.reset_model()
      ans_file.close()
  
imports: import argparse
  import torch
  import os
  import json
  from tqdm import tqdm
  import shortuuid
  from typing import Optional
  from llava.constants import IMAGE_TOKEN_INDEX, DEFAULT_IMAGE_TOKEN, DEFAULT_IM_START_TOKEN, DEFAULT_IM_END_TOKEN
  from llava.conversation import conv_templates, SeparatorStyle
  from llava.model.builder import load_pretrained_model
  from llava.utils import disable_torch_init
  from llava.mm_utils import tokenizer_image_token, process_images, get_model_name_from_path
  from torch.utils.data import Dataset, DataLoader
  import sys
  from highlighter_modules.utils import txt_highlight_mask
  from highlighter_modules.attention_llama_llava import llava_modify_inf
  from highlighter_modules.guidance import ProbCFGLogitsProcessor
  from PIL import Image
  import math
label_desc: Use image node_id 4 for calling a global function with example usage: eval_model(args) without return types