forked from krea-ai/krea-2
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathencoder.py
More file actions
76 lines (67 loc) · 2.93 KB
/
Copy pathencoder.py
File metadata and controls
76 lines (67 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
from dataclasses import dataclass
import torch
from torch import Tensor
from transformers import (
AutoTokenizer,
Qwen2TokenizerFast,
Qwen3VLForConditionalGeneration,
)
@dataclass
class TextEncoderConfig:
model_id: str
max_length: int = 512
select_layers: tuple[int, ...] = (2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35)
class Qwen3VLConditioner(torch.nn.Module):
def __init__(
self,
version: str,
max_length: int = 512,
select_layers: tuple[int, ...] = (2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35),
):
super().__init__()
self.qwen = Qwen3VLForConditionalGeneration.from_pretrained(version)
self.tokenizer = AutoTokenizer.from_pretrained(version, max_length=max_length)
self.processor = Qwen2TokenizerFast.from_pretrained(
version, max_length=max_length
)
self.qwen = self.qwen.eval().requires_grad_(False)
self.max_length = max_length
self.select_layers = select_layers
self.prompt_template_encode_prefix = "<|im_start|>system\nDescribe the image by detailing the color, shape, size, texture, quantity, text, spatial relationships of the objects and background:<|im_end|>\n<|im_start|>user\n"
self.prompt_template_encode_suffix = "<|im_end|>\n<|im_start|>assistant\n"
self.prompt_template_encode_start_idx = 34
self.prompt_template_encode_suffix_start_idx = 5
def forward(self, text: list[str]) -> tuple[Tensor, Tensor]:
prefix_idx = self.prompt_template_encode_start_idx
text = [self.prompt_template_encode_prefix + item for item in text]
suffix_text = [self.prompt_template_encode_suffix] * len(text)
suffix_inputs = self.processor(text=suffix_text, return_tensors="pt").to(
self.qwen.device, non_blocking=True
)
suffix_ids, suffix_mask = (
suffix_inputs["input_ids"],
suffix_inputs["attention_mask"].bool(),
)
with torch.no_grad():
inputs = self.tokenizer(
text,
truncation=True,
return_length=False,
return_overflowing_tokens=False,
padding="max_length",
max_length=self.max_length
+ prefix_idx
- self.prompt_template_encode_suffix_start_idx,
return_tensors="pt",
).to(self.qwen.device, non_blocking=True)
input_ids = torch.cat([inputs["input_ids"], suffix_ids], dim=1)
mask = torch.cat([inputs["attention_mask"].bool(), suffix_mask], dim=1)
states = self.qwen(
input_ids=input_ids, attention_mask=mask, output_hidden_states=True
)
hiddens = torch.stack(
[states.hidden_states[i] for i in self.select_layers], dim=2
)
hiddens = hiddens[:, prefix_idx:]
mask = mask[:, prefix_idx:]
return hiddens, mask