Views
No views yet
llamafactory installed.1git clone https://github.com/hiyouga/LLaMA-Factory.git
2cd LLaMA-Factory
3pip install -e .
4config.yaml)config.yaml file pointing to the base model and this adapter:1model_name_or_path: Kwai-Kolors/Keye-VL
2adapter_name_or_path: path_to_this_repo # or Local Path
3template: keye # Important: Must match Keye-VL template
4trust_remote_code: true
5finetuning_type: lora
61import torch
2import yaml
3from llamafactory.hparams import get_infer_args
4from llamafactory.model import load_tokenizer, get_template_and_fix_tokenizer
5from llamafactory.model import AutoModelForBinaryClassification
6from llamafactory.model.model_utils.classification_head import prepare_classification_model
7from llamafactory.model.patcher import patch_classification_model
8from transformers import AutoConfig, AutoModel
9
10class MemeScorer:
11 def __init__(self, config_path):
12 with open(config_path) as f:
13 config = yaml.safe_load(f)
14
15 # Force RM configuration
16 config.update({'stage': 'rm_class', 'finetuning_type': 'lora'})
17 model_args, data_args, _, _ = get_infer_args(config)
18
19 # 1. Load Tokenizer & Template
20 tokenizer_mod = load_tokenizer(model_args)
21 self.tokenizer = tokenizer_mod["tokenizer"]
22 self.processor = tokenizer_mod.get("processor")
23 self.template = get_template_and_fix_tokenizer(self.tokenizer, data_args)
24
25 # 2. Load Base Model
26 self.model = AutoModel.from_pretrained(
27 model_args.model_name_or_path,
28 trust_remote_code=True,
29 device_map="auto",
30 torch_dtype=torch.float16
31 )
32
33 # 3. Attach & Load Reward Head
34 prepare_classification_model(self.model)
35 self.model = AutoModelForBinaryClassification.from_pretrained(self.model)
36 patch_classification_model(self.model)
37
38 if model_args.adapter_name_or_path:
39 self.model.load_classification_head(model_args.adapter_name_or_path[0])
40 print("Loaded Humor Adapter.")
41
42 self.model.eval()
43
44 def score(self, img1_path, img2_path, prompt="Which meme is funnier?"):
45 # Construct Input
46 messages = [{"role": "user", "content": prompt}, {"role": "assistant", "content": ""}]
47 images = [img1_path, img2_path]
48
49 # Tokenize using Template
50 proc_msgs = self.template.mm_plugin.process_messages(messages, images, [], [], self.processor)
51 input_ids, _ = self.template.mm_plugin.process_token_ids([], [], images, [], [], self.tokenizer, self.processor)
52 encoded = self.template.encode_multiturn(self.tokenizer, proc_msgs, None, None)
53 input_ids += encoded[0][0]
54
55 # Forward Pass
56 inputs = {
57 "input_ids": torch.tensor([input_ids]).to(self.model.device),
58 "attention_mask": torch.tensor([[1]*len(input_ids)]).to(self.model.device),
59 "images": [images] # Image processor handling depends on Keye-VL version
60 }
61
62 with torch.no_grad():
63 logits = self.model(**inputs).logits.cpu().numpy()[0]
64
65 # Logits: [Score_Pair_0, Score_Pair_1] (Depends on exact head config, usually prob(A>B))
66 return logits
67
68# Usage
69if __name__ == "__main__":
70 scorer = MemeScorer("assets/config.yaml")
71 scores = scorer.score("assets/meme_a.jpg", "assets/meme_b.jpg")
72 print(f"Scores: {scores} (Winner: {'A' if scores[0] > scores[1] else 'B'})")
73
1@article{li2025perception,
2 title={From Perception to Punchline: Empowering VLM with the Art of In-the-wild Meme},
3 author={Li, Xueyan and Xue, Yingyi and Jiang, Mengjie and Zhu, Qingzi and Niu, Yazhe},
4 journal={arXiv preprint arXiv:2512.24555},
5 year={2025}
6}
7