JinghuiLuAstronaut commited on
Commit
c677f95
·
verified ·
1 Parent(s): 39803ff

Add files using upload-large-folder tool

Browse files
Files changed (20) hide show
  1. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/__init__.py +0 -0
  2. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/arithmetic.pyi +121 -0
  3. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/array_constructors.pyi +33 -0
  4. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/datasource.pyi +15 -0
  5. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/fromnumeric.pyi +161 -0
  6. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/memmap.pyi +5 -0
  7. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/nditer.pyi +8 -0
  8. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/numerictypes.pyi +11 -0
  9. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/stride_tricks.pyi +9 -0
  10. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/ufuncs.pyi +41 -0
  11. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/warnings_and_errors.pyi +5 -0
  12. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/mypy.ini +5 -0
  13. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/test_isfile.py +32 -0
  14. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/test_runtime.py +109 -0
  15. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/test_typing.py +300 -0
  16. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/qwen3_5/__init__.py +28 -0
  17. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/qwen3_5/configuration_qwen3_5.py +189 -0
  18. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/qwen3_5/modeling_qwen3_5.py +2152 -0
  19. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/qwen3_5/tokenization_qwen3_5.py +94 -0
  20. LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/sam2/modeling_sam2.py +1622 -0
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/__init__.py ADDED
File without changes
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/arithmetic.pyi ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any
2
+ import numpy as np
3
+
4
+ b_ = np.bool_()
5
+ dt = np.datetime64(0, "D")
6
+ td = np.timedelta64(0, "D")
7
+
8
+ AR_b: np.ndarray[Any, np.dtype[np.bool_]]
9
+ AR_u: np.ndarray[Any, np.dtype[np.uint32]]
10
+ AR_i: np.ndarray[Any, np.dtype[np.int64]]
11
+ AR_f: np.ndarray[Any, np.dtype[np.float64]]
12
+ AR_c: np.ndarray[Any, np.dtype[np.complex128]]
13
+ AR_m: np.ndarray[Any, np.dtype[np.timedelta64]]
14
+ AR_M: np.ndarray[Any, np.dtype[np.datetime64]]
15
+
16
+ ANY: Any
17
+
18
+ AR_LIKE_b: list[bool]
19
+ AR_LIKE_u: list[np.uint32]
20
+ AR_LIKE_i: list[int]
21
+ AR_LIKE_f: list[float]
22
+ AR_LIKE_c: list[complex]
23
+ AR_LIKE_m: list[np.timedelta64]
24
+ AR_LIKE_M: list[np.datetime64]
25
+
26
+ # Array subtraction
27
+
28
+ # NOTE: mypys `NoReturn` errors are, unfortunately, not that great
29
+ _1 = AR_b - AR_LIKE_b # E: Need type annotation
30
+ _2 = AR_LIKE_b - AR_b # E: Need type annotation
31
+ AR_i - bytes() # E: No overload variant
32
+
33
+ AR_f - AR_LIKE_m # E: Unsupported operand types
34
+ AR_f - AR_LIKE_M # E: Unsupported operand types
35
+ AR_c - AR_LIKE_m # E: Unsupported operand types
36
+ AR_c - AR_LIKE_M # E: Unsupported operand types
37
+
38
+ AR_m - AR_LIKE_f # E: Unsupported operand types
39
+ AR_M - AR_LIKE_f # E: Unsupported operand types
40
+ AR_m - AR_LIKE_c # E: Unsupported operand types
41
+ AR_M - AR_LIKE_c # E: Unsupported operand types
42
+
43
+ AR_m - AR_LIKE_M # E: Unsupported operand types
44
+ AR_LIKE_m - AR_M # E: Unsupported operand types
45
+
46
+ # array floor division
47
+
48
+ AR_M // AR_LIKE_b # E: Unsupported operand types
49
+ AR_M // AR_LIKE_u # E: Unsupported operand types
50
+ AR_M // AR_LIKE_i # E: Unsupported operand types
51
+ AR_M // AR_LIKE_f # E: Unsupported operand types
52
+ AR_M // AR_LIKE_c # E: Unsupported operand types
53
+ AR_M // AR_LIKE_m # E: Unsupported operand types
54
+ AR_M // AR_LIKE_M # E: Unsupported operand types
55
+
56
+ AR_b // AR_LIKE_M # E: Unsupported operand types
57
+ AR_u // AR_LIKE_M # E: Unsupported operand types
58
+ AR_i // AR_LIKE_M # E: Unsupported operand types
59
+ AR_f // AR_LIKE_M # E: Unsupported operand types
60
+ AR_c // AR_LIKE_M # E: Unsupported operand types
61
+ AR_m // AR_LIKE_M # E: Unsupported operand types
62
+ AR_M // AR_LIKE_M # E: Unsupported operand types
63
+
64
+ _3 = AR_m // AR_LIKE_b # E: Need type annotation
65
+ AR_m // AR_LIKE_c # E: Unsupported operand types
66
+
67
+ AR_b // AR_LIKE_m # E: Unsupported operand types
68
+ AR_u // AR_LIKE_m # E: Unsupported operand types
69
+ AR_i // AR_LIKE_m # E: Unsupported operand types
70
+ AR_f // AR_LIKE_m # E: Unsupported operand types
71
+ AR_c // AR_LIKE_m # E: Unsupported operand types
72
+
73
+ # Array multiplication
74
+
75
+ AR_b *= AR_LIKE_u # E: incompatible type
76
+ AR_b *= AR_LIKE_i # E: incompatible type
77
+ AR_b *= AR_LIKE_f # E: incompatible type
78
+ AR_b *= AR_LIKE_c # E: incompatible type
79
+ AR_b *= AR_LIKE_m # E: incompatible type
80
+
81
+ AR_u *= AR_LIKE_i # E: incompatible type
82
+ AR_u *= AR_LIKE_f # E: incompatible type
83
+ AR_u *= AR_LIKE_c # E: incompatible type
84
+ AR_u *= AR_LIKE_m # E: incompatible type
85
+
86
+ AR_i *= AR_LIKE_f # E: incompatible type
87
+ AR_i *= AR_LIKE_c # E: incompatible type
88
+ AR_i *= AR_LIKE_m # E: incompatible type
89
+
90
+ AR_f *= AR_LIKE_c # E: incompatible type
91
+ AR_f *= AR_LIKE_m # E: incompatible type
92
+
93
+ # Array power
94
+
95
+ AR_b **= AR_LIKE_b # E: Invalid self argument
96
+ AR_b **= AR_LIKE_u # E: Invalid self argument
97
+ AR_b **= AR_LIKE_i # E: Invalid self argument
98
+ AR_b **= AR_LIKE_f # E: Invalid self argument
99
+ AR_b **= AR_LIKE_c # E: Invalid self argument
100
+
101
+ AR_u **= AR_LIKE_i # E: incompatible type
102
+ AR_u **= AR_LIKE_f # E: incompatible type
103
+ AR_u **= AR_LIKE_c # E: incompatible type
104
+
105
+ AR_i **= AR_LIKE_f # E: incompatible type
106
+ AR_i **= AR_LIKE_c # E: incompatible type
107
+
108
+ AR_f **= AR_LIKE_c # E: incompatible type
109
+
110
+ # Scalars
111
+
112
+ b_ - b_ # E: No overload variant
113
+
114
+ dt + dt # E: Unsupported operand types
115
+ td - dt # E: Unsupported operand types
116
+ td % 1 # E: Unsupported operand types
117
+ td / dt # E: No overload
118
+ td % dt # E: Unsupported operand types
119
+
120
+ -b_ # E: Unsupported operand type
121
+ +b_ # E: Unsupported operand type
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/array_constructors.pyi ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ a: np.ndarray
4
+ generator = (i for i in range(10))
5
+
6
+ np.require(a, requirements=1) # E: No overload variant
7
+ np.require(a, requirements="TEST") # E: incompatible type
8
+
9
+ np.zeros("test") # E: incompatible type
10
+ np.zeros() # E: require at least one argument
11
+
12
+ np.ones("test") # E: incompatible type
13
+ np.ones() # E: require at least one argument
14
+
15
+ np.array(0, float, True) # E: No overload variant
16
+
17
+ np.linspace(None, 'bob') # E: No overload variant
18
+ np.linspace(0, 2, num=10.0) # E: No overload variant
19
+ np.linspace(0, 2, endpoint='True') # E: No overload variant
20
+ np.linspace(0, 2, retstep=b'False') # E: No overload variant
21
+ np.linspace(0, 2, dtype=0) # E: No overload variant
22
+ np.linspace(0, 2, axis=None) # E: No overload variant
23
+
24
+ np.logspace(None, 'bob') # E: No overload variant
25
+ np.logspace(0, 2, base=None) # E: No overload variant
26
+
27
+ np.geomspace(None, 'bob') # E: No overload variant
28
+
29
+ np.stack(generator) # E: No overload variant
30
+ np.hstack({1, 2}) # E: No overload variant
31
+ np.vstack(1) # E: No overload variant
32
+
33
+ np.array([1], like=1) # E: No overload variant
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/datasource.pyi ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import numpy as np
3
+
4
+ path: Path
5
+ d1: np.DataSource
6
+
7
+ d1.abspath(path) # E: incompatible type
8
+ d1.abspath(b"...") # E: incompatible type
9
+
10
+ d1.exists(path) # E: incompatible type
11
+ d1.exists(b"...") # E: incompatible type
12
+
13
+ d1.open(path, "r") # E: incompatible type
14
+ d1.open(b"...", encoding="utf8") # E: incompatible type
15
+ d1.open(None, newline="/n") # E: incompatible type
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/fromnumeric.pyi ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Tests for :mod:`numpy.core.fromnumeric`."""
2
+
3
+ import numpy as np
4
+ import numpy.typing as npt
5
+
6
+ A = np.array(True, ndmin=2, dtype=bool)
7
+ A.setflags(write=False)
8
+ AR_U: npt.NDArray[np.str_]
9
+
10
+ a = np.bool_(True)
11
+
12
+ np.take(a, None) # E: No overload variant
13
+ np.take(a, axis=1.0) # E: No overload variant
14
+ np.take(A, out=1) # E: No overload variant
15
+ np.take(A, mode="bob") # E: No overload variant
16
+
17
+ np.reshape(a, None) # E: No overload variant
18
+ np.reshape(A, 1, order="bob") # E: No overload variant
19
+
20
+ np.choose(a, None) # E: No overload variant
21
+ np.choose(a, out=1.0) # E: No overload variant
22
+ np.choose(A, mode="bob") # E: No overload variant
23
+
24
+ np.repeat(a, None) # E: No overload variant
25
+ np.repeat(A, 1, axis=1.0) # E: No overload variant
26
+
27
+ np.swapaxes(A, None, 1) # E: No overload variant
28
+ np.swapaxes(A, 1, [0]) # E: No overload variant
29
+
30
+ np.transpose(A, axes=1.0) # E: No overload variant
31
+
32
+ np.partition(a, None) # E: No overload variant
33
+ np.partition( # E: No overload variant
34
+ a, 0, axis="bob"
35
+ )
36
+ np.partition( # E: No overload variant
37
+ A, 0, kind="bob"
38
+ )
39
+ np.partition(
40
+ A, 0, order=range(5) # E: Argument "order" to "partition" has incompatible type
41
+ )
42
+
43
+ np.argpartition(
44
+ a, None # E: incompatible type
45
+ )
46
+ np.argpartition(
47
+ a, 0, axis="bob" # E: incompatible type
48
+ )
49
+ np.argpartition(
50
+ A, 0, kind="bob" # E: incompatible type
51
+ )
52
+ np.argpartition(
53
+ A, 0, order=range(5) # E: Argument "order" to "argpartition" has incompatible type
54
+ )
55
+
56
+ np.sort(A, axis="bob") # E: No overload variant
57
+ np.sort(A, kind="bob") # E: No overload variant
58
+ np.sort(A, order=range(5)) # E: Argument "order" to "sort" has incompatible type
59
+
60
+ np.argsort(A, axis="bob") # E: Argument "axis" to "argsort" has incompatible type
61
+ np.argsort(A, kind="bob") # E: Argument "kind" to "argsort" has incompatible type
62
+ np.argsort(A, order=range(5)) # E: Argument "order" to "argsort" has incompatible type
63
+
64
+ np.argmax(A, axis="bob") # E: No overload variant of "argmax" matches argument type
65
+ np.argmax(A, kind="bob") # E: No overload variant of "argmax" matches argument type
66
+
67
+ np.argmin(A, axis="bob") # E: No overload variant of "argmin" matches argument type
68
+ np.argmin(A, kind="bob") # E: No overload variant of "argmin" matches argument type
69
+
70
+ np.searchsorted( # E: No overload variant of "searchsorted" matches argument type
71
+ A[0], 0, side="bob"
72
+ )
73
+ np.searchsorted( # E: No overload variant of "searchsorted" matches argument type
74
+ A[0], 0, sorter=1.0
75
+ )
76
+
77
+ np.resize(A, 1.0) # E: No overload variant
78
+
79
+ np.squeeze(A, 1.0) # E: No overload variant of "squeeze" matches argument type
80
+
81
+ np.diagonal(A, offset=None) # E: No overload variant
82
+ np.diagonal(A, axis1="bob") # E: No overload variant
83
+ np.diagonal(A, axis2=[]) # E: No overload variant
84
+
85
+ np.trace(A, offset=None) # E: No overload variant
86
+ np.trace(A, axis1="bob") # E: No overload variant
87
+ np.trace(A, axis2=[]) # E: No overload variant
88
+
89
+ np.ravel(a, order="bob") # E: No overload variant
90
+
91
+ np.compress( # E: No overload variant
92
+ [True], A, axis=1.0
93
+ )
94
+
95
+ np.clip(a, 1, 2, out=1) # E: No overload variant of "clip" matches argument type
96
+
97
+ np.sum(a, axis=1.0) # E: No overload variant
98
+ np.sum(a, keepdims=1.0) # E: No overload variant
99
+ np.sum(a, initial=[1]) # E: No overload variant
100
+
101
+ np.all(a, axis=1.0) # E: No overload variant
102
+ np.all(a, keepdims=1.0) # E: No overload variant
103
+ np.all(a, out=1.0) # E: No overload variant
104
+
105
+ np.any(a, axis=1.0) # E: No overload variant
106
+ np.any(a, keepdims=1.0) # E: No overload variant
107
+ np.any(a, out=1.0) # E: No overload variant
108
+
109
+ np.cumsum(a, axis=1.0) # E: No overload variant
110
+ np.cumsum(a, dtype=1.0) # E: No overload variant
111
+ np.cumsum(a, out=1.0) # E: No overload variant
112
+
113
+ np.ptp(a, axis=1.0) # E: No overload variant
114
+ np.ptp(a, keepdims=1.0) # E: No overload variant
115
+ np.ptp(a, out=1.0) # E: No overload variant
116
+
117
+ np.amax(a, axis=1.0) # E: No overload variant
118
+ np.amax(a, keepdims=1.0) # E: No overload variant
119
+ np.amax(a, out=1.0) # E: No overload variant
120
+ np.amax(a, initial=[1.0]) # E: No overload variant
121
+ np.amax(a, where=[1.0]) # E: incompatible type
122
+
123
+ np.amin(a, axis=1.0) # E: No overload variant
124
+ np.amin(a, keepdims=1.0) # E: No overload variant
125
+ np.amin(a, out=1.0) # E: No overload variant
126
+ np.amin(a, initial=[1.0]) # E: No overload variant
127
+ np.amin(a, where=[1.0]) # E: incompatible type
128
+
129
+ np.prod(a, axis=1.0) # E: No overload variant
130
+ np.prod(a, out=False) # E: No overload variant
131
+ np.prod(a, keepdims=1.0) # E: No overload variant
132
+ np.prod(a, initial=int) # E: No overload variant
133
+ np.prod(a, where=1.0) # E: No overload variant
134
+ np.prod(AR_U) # E: incompatible type
135
+
136
+ np.cumprod(a, axis=1.0) # E: No overload variant
137
+ np.cumprod(a, out=False) # E: No overload variant
138
+ np.cumprod(AR_U) # E: incompatible type
139
+
140
+ np.size(a, axis=1.0) # E: Argument "axis" to "size" has incompatible type
141
+
142
+ np.around(a, decimals=1.0) # E: No overload variant
143
+ np.around(a, out=type) # E: No overload variant
144
+ np.around(AR_U) # E: incompatible type
145
+
146
+ np.mean(a, axis=1.0) # E: No overload variant
147
+ np.mean(a, out=False) # E: No overload variant
148
+ np.mean(a, keepdims=1.0) # E: No overload variant
149
+ np.mean(AR_U) # E: incompatible type
150
+
151
+ np.std(a, axis=1.0) # E: No overload variant
152
+ np.std(a, out=False) # E: No overload variant
153
+ np.std(a, ddof='test') # E: No overload variant
154
+ np.std(a, keepdims=1.0) # E: No overload variant
155
+ np.std(AR_U) # E: incompatible type
156
+
157
+ np.var(a, axis=1.0) # E: No overload variant
158
+ np.var(a, out=False) # E: No overload variant
159
+ np.var(a, ddof='test') # E: No overload variant
160
+ np.var(a, keepdims=1.0) # E: No overload variant
161
+ np.var(AR_U) # E: incompatible type
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/memmap.pyi ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ with open("file.txt", "r") as f:
4
+ np.memmap(f) # E: No overload variant
5
+ np.memmap("test.txt", shape=[10, 5]) # E: No overload variant
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/nditer.pyi ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ class Test(np.nditer): ... # E: Cannot inherit from final class
4
+
5
+ np.nditer([0, 1], flags=["test"]) # E: incompatible type
6
+ np.nditer([0, 1], op_flags=[["test"]]) # E: incompatible type
7
+ np.nditer([0, 1], itershape=(1.0,)) # E: incompatible type
8
+ np.nditer([0, 1], buffersize=1.0) # E: incompatible type
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/numerictypes.pyi ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ # Technically this works, but probably shouldn't. See
4
+ #
5
+ # https://github.com/numpy/numpy/issues/16366
6
+ #
7
+ np.maximum_sctype(1) # E: No overload variant
8
+
9
+ np.issubsctype(1, np.int64) # E: incompatible type
10
+
11
+ np.issubdtype(1, np.int64) # E: incompatible type
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/stride_tricks.pyi ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import numpy.typing as npt
3
+
4
+ AR_f8: npt.NDArray[np.float64]
5
+
6
+ np.lib.stride_tricks.as_strided(AR_f8, shape=8) # E: No overload variant
7
+ np.lib.stride_tricks.as_strided(AR_f8, strides=8) # E: No overload variant
8
+
9
+ np.lib.stride_tricks.sliding_window_view(AR_f8, axis=(1,)) # E: No overload variant
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/ufuncs.pyi ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import numpy.typing as npt
3
+
4
+ AR_f8: npt.NDArray[np.float64]
5
+
6
+ np.sin.nin + "foo" # E: Unsupported operand types
7
+ np.sin(1, foo="bar") # E: No overload variant
8
+
9
+ np.abs(None) # E: No overload variant
10
+
11
+ np.add(1, 1, 1) # E: No overload variant
12
+ np.add(1, 1, axis=0) # E: No overload variant
13
+
14
+ np.matmul(AR_f8, AR_f8, where=True) # E: No overload variant
15
+
16
+ np.frexp(AR_f8, out=None) # E: No overload variant
17
+ np.frexp(AR_f8, out=AR_f8) # E: No overload variant
18
+
19
+ np.absolute.outer() # E: "None" not callable
20
+ np.frexp.outer() # E: "None" not callable
21
+ np.divmod.outer() # E: "None" not callable
22
+ np.matmul.outer() # E: "None" not callable
23
+
24
+ np.absolute.reduceat() # E: "None" not callable
25
+ np.frexp.reduceat() # E: "None" not callable
26
+ np.divmod.reduceat() # E: "None" not callable
27
+ np.matmul.reduceat() # E: "None" not callable
28
+
29
+ np.absolute.reduce() # E: "None" not callable
30
+ np.frexp.reduce() # E: "None" not callable
31
+ np.divmod.reduce() # E: "None" not callable
32
+ np.matmul.reduce() # E: "None" not callable
33
+
34
+ np.absolute.accumulate() # E: "None" not callable
35
+ np.frexp.accumulate() # E: "None" not callable
36
+ np.divmod.accumulate() # E: "None" not callable
37
+ np.matmul.accumulate() # E: "None" not callable
38
+
39
+ np.frexp.at() # E: "None" not callable
40
+ np.divmod.at() # E: "None" not callable
41
+ np.matmul.at() # E: "None" not callable
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/fail/warnings_and_errors.pyi ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ import numpy as np
2
+
3
+ np.AxisError(1.0) # E: No overload variant
4
+ np.AxisError(1, ndim=2.0) # E: No overload variant
5
+ np.AxisError(2, msg_prefix=404) # E: No overload variant
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/data/mypy.ini ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ [mypy]
2
+ plugins = numpy.typing.mypy_plugin
3
+ show_absolute_path = True
4
+ implicit_reexport = False
5
+ pretty = True
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/test_isfile.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ from pathlib import Path
4
+
5
+ import numpy as np
6
+ from numpy.testing import assert_
7
+
8
+ ROOT = Path(np.__file__).parents[0]
9
+ FILES = [
10
+ ROOT / "py.typed",
11
+ ROOT / "__init__.pyi",
12
+ ROOT / "ctypeslib.pyi",
13
+ ROOT / "core" / "__init__.pyi",
14
+ ROOT / "f2py" / "__init__.pyi",
15
+ ROOT / "fft" / "__init__.pyi",
16
+ ROOT / "lib" / "__init__.pyi",
17
+ ROOT / "linalg" / "__init__.pyi",
18
+ ROOT / "ma" / "__init__.pyi",
19
+ ROOT / "matrixlib" / "__init__.pyi",
20
+ ROOT / "polynomial" / "__init__.pyi",
21
+ ROOT / "random" / "__init__.pyi",
22
+ ROOT / "testing" / "__init__.pyi",
23
+ ]
24
+ if sys.version_info < (3, 12):
25
+ FILES += [ROOT / "distutils" / "__init__.pyi"]
26
+
27
+
28
+ class TestIsFile:
29
+ def test_isfile(self):
30
+ """Test if all ``.pyi`` files are properly installed."""
31
+ for file in FILES:
32
+ assert_(os.path.isfile(file))
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/test_runtime.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Test the runtime usage of `numpy.typing`."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import (
6
+ get_type_hints,
7
+ Union,
8
+ NamedTuple,
9
+ get_args,
10
+ get_origin,
11
+ Any,
12
+ )
13
+
14
+ import pytest
15
+ import numpy as np
16
+ import numpy.typing as npt
17
+ import numpy._typing as _npt
18
+
19
+
20
+ class TypeTup(NamedTuple):
21
+ typ: type
22
+ args: tuple[type, ...]
23
+ origin: None | type
24
+
25
+
26
+ NDArrayTup = TypeTup(npt.NDArray, npt.NDArray.__args__, np.ndarray)
27
+
28
+ TYPES = {
29
+ "ArrayLike": TypeTup(npt.ArrayLike, npt.ArrayLike.__args__, Union),
30
+ "DTypeLike": TypeTup(npt.DTypeLike, npt.DTypeLike.__args__, Union),
31
+ "NBitBase": TypeTup(npt.NBitBase, (), None),
32
+ "NDArray": NDArrayTup,
33
+ }
34
+
35
+
36
+ @pytest.mark.parametrize("name,tup", TYPES.items(), ids=TYPES.keys())
37
+ def test_get_args(name: type, tup: TypeTup) -> None:
38
+ """Test `typing.get_args`."""
39
+ typ, ref = tup.typ, tup.args
40
+ out = get_args(typ)
41
+ assert out == ref
42
+
43
+
44
+ @pytest.mark.parametrize("name,tup", TYPES.items(), ids=TYPES.keys())
45
+ def test_get_origin(name: type, tup: TypeTup) -> None:
46
+ """Test `typing.get_origin`."""
47
+ typ, ref = tup.typ, tup.origin
48
+ out = get_origin(typ)
49
+ assert out == ref
50
+
51
+
52
+ @pytest.mark.parametrize("name,tup", TYPES.items(), ids=TYPES.keys())
53
+ def test_get_type_hints(name: type, tup: TypeTup) -> None:
54
+ """Test `typing.get_type_hints`."""
55
+ typ = tup.typ
56
+
57
+ # Explicitly set `__annotations__` in order to circumvent the
58
+ # stringification performed by `from __future__ import annotations`
59
+ def func(a): pass
60
+ func.__annotations__ = {"a": typ, "return": None}
61
+
62
+ out = get_type_hints(func)
63
+ ref = {"a": typ, "return": type(None)}
64
+ assert out == ref
65
+
66
+
67
+ @pytest.mark.parametrize("name,tup", TYPES.items(), ids=TYPES.keys())
68
+ def test_get_type_hints_str(name: type, tup: TypeTup) -> None:
69
+ """Test `typing.get_type_hints` with string-representation of types."""
70
+ typ_str, typ = f"npt.{name}", tup.typ
71
+
72
+ # Explicitly set `__annotations__` in order to circumvent the
73
+ # stringification performed by `from __future__ import annotations`
74
+ def func(a): pass
75
+ func.__annotations__ = {"a": typ_str, "return": None}
76
+
77
+ out = get_type_hints(func)
78
+ ref = {"a": typ, "return": type(None)}
79
+ assert out == ref
80
+
81
+
82
+ def test_keys() -> None:
83
+ """Test that ``TYPES.keys()`` and ``numpy.typing.__all__`` are synced."""
84
+ keys = TYPES.keys()
85
+ ref = set(npt.__all__)
86
+ assert keys == ref
87
+
88
+
89
+ PROTOCOLS: dict[str, tuple[type[Any], object]] = {
90
+ "_SupportsDType": (_npt._SupportsDType, np.int64(1)),
91
+ "_SupportsArray": (_npt._SupportsArray, np.arange(10)),
92
+ "_SupportsArrayFunc": (_npt._SupportsArrayFunc, np.arange(10)),
93
+ "_NestedSequence": (_npt._NestedSequence, [1]),
94
+ }
95
+
96
+
97
+ @pytest.mark.parametrize("cls,obj", PROTOCOLS.values(), ids=PROTOCOLS.keys())
98
+ class TestRuntimeProtocol:
99
+ def test_isinstance(self, cls: type[Any], obj: object) -> None:
100
+ assert isinstance(obj, cls)
101
+ assert not isinstance(None, cls)
102
+
103
+ def test_issubclass(self, cls: type[Any], obj: object) -> None:
104
+ if cls is _npt._SupportsDType:
105
+ pytest.xfail(
106
+ "Protocols with non-method members don't support issubclass()"
107
+ )
108
+ assert issubclass(type(obj), cls)
109
+ assert not issubclass(type(None), cls)
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/numpy/typing/tests/test_typing.py ADDED
@@ -0,0 +1,300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import importlib.util
4
+ import os
5
+ import re
6
+ import shutil
7
+ from collections import defaultdict
8
+ from collections.abc import Iterator
9
+ from typing import TYPE_CHECKING
10
+
11
+ import pytest
12
+ from numpy.typing.mypy_plugin import _EXTENDED_PRECISION_LIST
13
+
14
+
15
+ # Only trigger a full `mypy` run if this environment variable is set
16
+ # Note that these tests tend to take over a minute even on a macOS M1 CPU,
17
+ # and more than that in CI.
18
+ RUN_MYPY = "NPY_RUN_MYPY_IN_TESTSUITE" in os.environ
19
+ if RUN_MYPY and RUN_MYPY not in ('0', '', 'false'):
20
+ RUN_MYPY = True
21
+
22
+ # Skips all functions in this file
23
+ pytestmark = pytest.mark.skipif(
24
+ not RUN_MYPY,
25
+ reason="`NPY_RUN_MYPY_IN_TESTSUITE` not set"
26
+ )
27
+
28
+
29
+ # Only trigger a full `mypy` run if this environment variable is set
30
+ # Note that these tests tend to take over a minute even on a macOS M1 CPU,
31
+ # and more than that in CI.
32
+ RUN_MYPY = "NPY_RUN_MYPY_IN_TESTSUITE" in os.environ
33
+ if RUN_MYPY and RUN_MYPY not in ('0', '', 'false'):
34
+ RUN_MYPY = True
35
+
36
+ # Skips all functions in this file
37
+ pytestmark = pytest.mark.skipif(
38
+ not RUN_MYPY,
39
+ reason="`NPY_RUN_MYPY_IN_TESTSUITE` not set"
40
+ )
41
+
42
+
43
+ try:
44
+ from mypy import api
45
+ except ImportError:
46
+ NO_MYPY = True
47
+ else:
48
+ NO_MYPY = False
49
+
50
+ if TYPE_CHECKING:
51
+ # We need this as annotation, but it's located in a private namespace.
52
+ # As a compromise, do *not* import it during runtime
53
+ from _pytest.mark.structures import ParameterSet
54
+
55
+ DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
56
+ PASS_DIR = os.path.join(DATA_DIR, "pass")
57
+ FAIL_DIR = os.path.join(DATA_DIR, "fail")
58
+ REVEAL_DIR = os.path.join(DATA_DIR, "reveal")
59
+ MISC_DIR = os.path.join(DATA_DIR, "misc")
60
+ MYPY_INI = os.path.join(DATA_DIR, "mypy.ini")
61
+ CACHE_DIR = os.path.join(DATA_DIR, ".mypy_cache")
62
+
63
+ #: A dictionary with file names as keys and lists of the mypy stdout as values.
64
+ #: To-be populated by `run_mypy`.
65
+ OUTPUT_MYPY: defaultdict[str, list[str]] = defaultdict(list)
66
+
67
+
68
+ def _key_func(key: str) -> str:
69
+ """Split at the first occurrence of the ``:`` character.
70
+
71
+ Windows drive-letters (*e.g.* ``C:``) are ignored herein.
72
+ """
73
+ drive, tail = os.path.splitdrive(key)
74
+ return os.path.join(drive, tail.split(":", 1)[0])
75
+
76
+
77
+ def _strip_filename(msg: str) -> tuple[int, str]:
78
+ """Strip the filename and line number from a mypy message."""
79
+ _, tail = os.path.splitdrive(msg)
80
+ _, lineno, msg = tail.split(":", 2)
81
+ return int(lineno), msg.strip()
82
+
83
+
84
+ def strip_func(match: re.Match[str]) -> str:
85
+ """`re.sub` helper function for stripping module names."""
86
+ return match.groups()[1]
87
+
88
+
89
+ @pytest.fixture(scope="module", autouse=True)
90
+ def run_mypy() -> None:
91
+ """Clears the cache and run mypy before running any of the typing tests.
92
+
93
+ The mypy results are cached in `OUTPUT_MYPY` for further use.
94
+
95
+ The cache refresh can be skipped using
96
+
97
+ NUMPY_TYPING_TEST_CLEAR_CACHE=0 pytest numpy/typing/tests
98
+ """
99
+ if (
100
+ os.path.isdir(CACHE_DIR)
101
+ and bool(os.environ.get("NUMPY_TYPING_TEST_CLEAR_CACHE", True))
102
+ ):
103
+ shutil.rmtree(CACHE_DIR)
104
+
105
+ split_pattern = re.compile(r"(\s+)?\^(\~+)?")
106
+ for directory in (PASS_DIR, REVEAL_DIR, FAIL_DIR, MISC_DIR):
107
+ # Run mypy
108
+ stdout, stderr, exit_code = api.run([
109
+ "--config-file",
110
+ MYPY_INI,
111
+ "--cache-dir",
112
+ CACHE_DIR,
113
+ directory,
114
+ ])
115
+ if stderr:
116
+ pytest.fail(f"Unexpected mypy standard error\n\n{stderr}")
117
+ elif exit_code not in {0, 1}:
118
+ pytest.fail(f"Unexpected mypy exit code: {exit_code}\n\n{stdout}")
119
+
120
+ str_concat = ""
121
+ filename: str | None = None
122
+ for i in stdout.split("\n"):
123
+ if "note:" in i:
124
+ continue
125
+ if filename is None:
126
+ filename = _key_func(i)
127
+
128
+ str_concat += f"{i}\n"
129
+ if split_pattern.match(i) is not None:
130
+ OUTPUT_MYPY[filename].append(str_concat)
131
+ str_concat = ""
132
+ filename = None
133
+
134
+
135
+ def get_test_cases(directory: str) -> Iterator[ParameterSet]:
136
+ for root, _, files in os.walk(directory):
137
+ for fname in files:
138
+ short_fname, ext = os.path.splitext(fname)
139
+ if ext in (".pyi", ".py"):
140
+ fullpath = os.path.join(root, fname)
141
+ yield pytest.param(fullpath, id=short_fname)
142
+
143
+
144
+ @pytest.mark.slow
145
+ @pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
146
+ @pytest.mark.parametrize("path", get_test_cases(PASS_DIR))
147
+ def test_success(path) -> None:
148
+ # Alias `OUTPUT_MYPY` so that it appears in the local namespace
149
+ output_mypy = OUTPUT_MYPY
150
+ if path in output_mypy:
151
+ msg = "Unexpected mypy output\n\n"
152
+ msg += "\n".join(_strip_filename(v)[1] for v in output_mypy[path])
153
+ raise AssertionError(msg)
154
+
155
+
156
+ @pytest.mark.slow
157
+ @pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
158
+ @pytest.mark.parametrize("path", get_test_cases(FAIL_DIR))
159
+ def test_fail(path: str) -> None:
160
+ __tracebackhide__ = True
161
+
162
+ with open(path) as fin:
163
+ lines = fin.readlines()
164
+
165
+ errors = defaultdict(lambda: "")
166
+
167
+ output_mypy = OUTPUT_MYPY
168
+ assert path in output_mypy
169
+
170
+ for error_line in output_mypy[path]:
171
+ lineno, error_line = _strip_filename(error_line)
172
+ errors[lineno] += f'{error_line}\n'
173
+
174
+ for i, line in enumerate(lines):
175
+ lineno = i + 1
176
+ if (
177
+ line.startswith('#')
178
+ or (" E:" not in line and lineno not in errors)
179
+ ):
180
+ continue
181
+
182
+ target_line = lines[lineno - 1]
183
+ if "# E:" in target_line:
184
+ expression, _, marker = target_line.partition(" # E: ")
185
+ expected_error = errors[lineno].strip()
186
+ marker = marker.strip()
187
+ _test_fail(path, expression, marker, expected_error, lineno)
188
+ else:
189
+ pytest.fail(
190
+ f"Unexpected mypy output at line {lineno}\n\n{errors[lineno]}"
191
+ )
192
+
193
+
194
+ _FAIL_MSG1 = """Extra error at line {}
195
+
196
+ Expression: {}
197
+ Extra error: {!r}
198
+ """
199
+
200
+ _FAIL_MSG2 = """Error mismatch at line {}
201
+
202
+ Expression: {}
203
+ Expected error: {}
204
+ Observed error: {!r}
205
+ """
206
+
207
+
208
+ def _test_fail(
209
+ path: str,
210
+ expression: str,
211
+ error: str,
212
+ expected_error: None | str,
213
+ lineno: int,
214
+ ) -> None:
215
+ if expected_error is None:
216
+ raise AssertionError(_FAIL_MSG1.format(lineno, expression, error))
217
+ elif error not in expected_error:
218
+ raise AssertionError(_FAIL_MSG2.format(
219
+ lineno, expression, expected_error, error
220
+ ))
221
+
222
+
223
+ _REVEAL_MSG = """Reveal mismatch at line {}
224
+
225
+ {}
226
+ """
227
+
228
+
229
+ @pytest.mark.slow
230
+ @pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
231
+ @pytest.mark.parametrize("path", get_test_cases(REVEAL_DIR))
232
+ def test_reveal(path: str) -> None:
233
+ """Validate that mypy correctly infers the return-types of
234
+ the expressions in `path`.
235
+ """
236
+ __tracebackhide__ = True
237
+
238
+ output_mypy = OUTPUT_MYPY
239
+ if path not in output_mypy:
240
+ return
241
+
242
+ for error_line in output_mypy[path]:
243
+ lineno, error_line = _strip_filename(error_line)
244
+ raise AssertionError(_REVEAL_MSG.format(lineno, error_line))
245
+
246
+
247
+ @pytest.mark.slow
248
+ @pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
249
+ @pytest.mark.parametrize("path", get_test_cases(PASS_DIR))
250
+ def test_code_runs(path: str) -> None:
251
+ """Validate that the code in `path` properly during runtime."""
252
+ path_without_extension, _ = os.path.splitext(path)
253
+ dirname, filename = path.split(os.sep)[-2:]
254
+
255
+ spec = importlib.util.spec_from_file_location(
256
+ f"{dirname}.{filename}", path
257
+ )
258
+ assert spec is not None
259
+ assert spec.loader is not None
260
+
261
+ test_module = importlib.util.module_from_spec(spec)
262
+ spec.loader.exec_module(test_module)
263
+
264
+
265
+ LINENO_MAPPING = {
266
+ 11: "uint128",
267
+ 12: "uint256",
268
+ 14: "int128",
269
+ 15: "int256",
270
+ 17: "float80",
271
+ 18: "float96",
272
+ 19: "float128",
273
+ 20: "float256",
274
+ 22: "complex160",
275
+ 23: "complex192",
276
+ 24: "complex256",
277
+ 25: "complex512",
278
+ }
279
+
280
+
281
+ @pytest.mark.slow
282
+ @pytest.mark.skipif(NO_MYPY, reason="Mypy is not installed")
283
+ def test_extended_precision() -> None:
284
+ path = os.path.join(MISC_DIR, "extended_precision.pyi")
285
+ output_mypy = OUTPUT_MYPY
286
+ assert path in output_mypy
287
+
288
+ with open(path) as f:
289
+ expression_list = f.readlines()
290
+
291
+ for _msg in output_mypy[path]:
292
+ lineno, msg = _strip_filename(_msg)
293
+ expression = expression_list[lineno - 1].rstrip("\n")
294
+
295
+ if LINENO_MAPPING[lineno] in _EXTENDED_PRECISION_LIST:
296
+ raise AssertionError(_REVEAL_MSG.format(lineno, msg))
297
+ elif "error" not in msg:
298
+ _test_fail(
299
+ path, expression, msg, 'Expression is of type "Any"', lineno
300
+ )
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/qwen3_5/__init__.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2025 The HuggingFace Team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from typing import TYPE_CHECKING
15
+
16
+ from ...utils import _LazyModule
17
+ from ...utils.import_utils import define_import_structure
18
+
19
+
20
+ if TYPE_CHECKING:
21
+ from .configuration_qwen3_5 import *
22
+ from .modeling_qwen3_5 import *
23
+ from .tokenization_qwen3_5 import *
24
+ else:
25
+ import sys
26
+
27
+ _file = globals()["__file__"]
28
+ sys.modules[__name__] = _LazyModule(__name__, _file, define_import_structure(_file), module_spec=__spec__)
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/qwen3_5/configuration_qwen3_5.py ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
2
+ # This file was automatically generated from src/transformers/models/qwen3_5/modular_qwen3_5.py.
3
+ # Do NOT edit this file manually as any edits will be overwritten by the generation of
4
+ # the file from the modular. If any change should be done, please apply the change to the
5
+ # modular_qwen3_5.py file directly. One of our CI enforces this.
6
+ # 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
7
+ # Copyright 2025 The Qwen Team and The HuggingFace Inc. team. All rights reserved.
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+ from huggingface_hub.dataclasses import strict
21
+
22
+ from ...configuration_utils import PreTrainedConfig
23
+ from ...modeling_rope_utils import RopeParameters
24
+ from ...utils import auto_docstring
25
+
26
+
27
+ @auto_docstring(checkpoint="Qwen/Qwen3.5-27B")
28
+ @strict
29
+ class Qwen3_5TextConfig(PreTrainedConfig):
30
+ r"""
31
+ linear_conv_kernel_dim (`int`, *optional*, defaults to 4):
32
+ Kernel size of the convolution used in linear attention layers.
33
+ linear_key_head_dim (`int`, *optional*, defaults to 128):
34
+ Dimension of each key head in linear attention.
35
+ linear_value_head_dim (`int`, *optional*, defaults to 128):
36
+ Dimension of each value head in linear attention.
37
+ linear_num_key_heads (`int`, *optional*, defaults to 16):
38
+ Number of key heads used in linear attention layers.
39
+ linear_num_value_heads (`int`, *optional*, defaults to 32):
40
+ Number of value heads used in linear attention layers.
41
+
42
+ ```python
43
+ >>> from transformers import Qwen3_5TextModel, Qwen3_5TextConfig
44
+
45
+ >>> # Initializing a Qwen3.5 style configuration
46
+ >>> configuration = Qwen3_5TextConfig()
47
+
48
+ >>> # Initializing a model from the Qwen3.5-9B style configuration
49
+ >>> model = Qwen3_5TextModel(configuration)
50
+
51
+ >>> # Accessing the model configuration
52
+ >>> configuration = model.config
53
+ ```
54
+ """
55
+
56
+ model_type = "qwen3_5_text"
57
+ keys_to_ignore_at_inference = ["past_key_values"]
58
+
59
+ base_model_tp_plan = {
60
+ "layers.*.self_attn.q_proj": "colwise",
61
+ "layers.*.self_attn.k_proj": "colwise",
62
+ "layers.*.self_attn.v_proj": "colwise",
63
+ "layers.*.self_attn.o_proj": "rowwise",
64
+ "layers.*.self_attn.q_norm": "replicated_with_grad_allreduce",
65
+ "layers.*.self_attn.k_norm": "replicated_with_grad_allreduce",
66
+ "layers.*.mlp.gate_proj": "colwise",
67
+ "layers.*.mlp.up_proj": "colwise",
68
+ "layers.*.mlp.down_proj": "rowwise",
69
+ }
70
+ base_model_pp_plan = {
71
+ "embed_tokens": (["input_ids"], ["inputs_embeds"]),
72
+ "layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
73
+ "norm": (["hidden_states"], ["hidden_states"]),
74
+ }
75
+
76
+ vocab_size: int = 248320
77
+ hidden_size: int = 4096
78
+ intermediate_size: int = 12288
79
+ num_hidden_layers: int = 32
80
+ num_attention_heads: int = 16
81
+ num_key_value_heads: int = 4
82
+ hidden_act: str = "silu"
83
+ max_position_embeddings: int = 32768
84
+ initializer_range: float = 0.02
85
+ rms_norm_eps: float = 1e-6
86
+ use_cache: bool = True
87
+ tie_word_embeddings: bool = False
88
+ rope_parameters: RopeParameters | dict | None = None
89
+ attention_bias: bool = False
90
+ attention_dropout: float | int = 0.0
91
+ head_dim: int = 256
92
+ linear_conv_kernel_dim: int = 4
93
+ linear_key_head_dim: int = 128
94
+ linear_value_head_dim: int = 128
95
+ linear_num_key_heads: int = 16
96
+ linear_num_value_heads: int = 32
97
+ layer_types: list[str] | None = None
98
+ pad_token_id: int | None = None
99
+ bos_token_id: int | None = None
100
+ eos_token_id: int | list[int] | None = None
101
+ base_config_key = "text_config"
102
+ ignore_keys_at_rope_validation = {"mrope_section", "mrope_interleaved"}
103
+
104
+ def __post_init__(self, **kwargs):
105
+ kwargs.setdefault("partial_rotary_factor", 0.25) # assign default for BC
106
+ if self.layer_types is None:
107
+ interval_pattern = kwargs.pop("full_attention_interval", 4)
108
+ self.layer_types = [
109
+ "linear_attention" if bool((i + 1) % interval_pattern) else "full_attention"
110
+ for i in range(self.num_hidden_layers)
111
+ ]
112
+
113
+ super().__post_init__(**kwargs)
114
+
115
+
116
+ @auto_docstring(checkpoint="Qwen/Qwen3.5-27B")
117
+ @strict
118
+ class Qwen3_5VisionConfig(PreTrainedConfig):
119
+ r"""
120
+ out_hidden_size (`int`, *optional*, defaults to 3584):
121
+ The output hidden size of the vision model.
122
+ num_position_embeddings (`int`, *optional*, defaults to 2304):
123
+ The maximum sequence length that this model might ever be used with
124
+ """
125
+
126
+ model_type = "qwen3_5_vision"
127
+ base_config_key = "vision_config"
128
+
129
+ depth: int = 27
130
+ hidden_size: int = 1152
131
+ hidden_act: str = "gelu_pytorch_tanh"
132
+ intermediate_size: int = 4304
133
+ num_heads: int = 16
134
+ in_channels: int = 3
135
+ patch_size: int | list[int] | tuple[int, int] = 16
136
+ spatial_merge_size: int = 2
137
+ temporal_patch_size: int | list[int] | tuple[int, int] = 2
138
+ out_hidden_size: int = 3584
139
+ num_position_embeddings: int = 2304
140
+ initializer_range: float = 0.02
141
+
142
+
143
+ @auto_docstring(checkpoint="Qwen/Qwen3.5-27B")
144
+ @strict
145
+ class Qwen3_5Config(PreTrainedConfig):
146
+ r"""
147
+ Example:
148
+
149
+ ```python
150
+ >>> from transformers import Qwen3_5ForConditionalGeneration, Qwen3_5Config
151
+
152
+ >>> # Initializing a Qwen3.5 style configuration
153
+ >>> configuration = Qwen3_5Config()
154
+
155
+ >>> # Initializing a model from the Qwen3.5-9B style configuration
156
+ >>> model = Qwen3_5ForConditionalGeneration(configuration)
157
+
158
+ >>> # Accessing the model configuration
159
+ >>> configuration = model.config
160
+ ```"""
161
+
162
+ model_type = "qwen3_5"
163
+ sub_configs = {"vision_config": Qwen3_5VisionConfig, "text_config": Qwen3_5TextConfig}
164
+ keys_to_ignore_at_inference = ["past_key_values"]
165
+
166
+ text_config: dict | PreTrainedConfig | None = None
167
+ vision_config: dict | PreTrainedConfig | None = None
168
+
169
+ image_token_id: int = 248056
170
+ video_token_id: int = 248057
171
+ vision_start_token_id: int = 248053
172
+ vision_end_token_id: int = 248054
173
+ tie_word_embeddings: bool = False
174
+
175
+ def __post_init__(self, **kwargs):
176
+ if isinstance(self.vision_config, dict):
177
+ self.vision_config = self.sub_configs["vision_config"](**self.vision_config)
178
+ elif self.vision_config is None:
179
+ self.vision_config = self.sub_configs["vision_config"]()
180
+
181
+ if isinstance(self.text_config, dict):
182
+ self.text_config = self.sub_configs["text_config"](**self.text_config)
183
+ elif self.text_config is None:
184
+ self.text_config = self.sub_configs["text_config"]()
185
+
186
+ super().__post_init__(**kwargs)
187
+
188
+
189
+ __all__ = ["Qwen3_5Config", "Qwen3_5TextConfig", "Qwen3_5VisionConfig"]
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/qwen3_5/modeling_qwen3_5.py ADDED
@@ -0,0 +1,2152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
2
+ # This file was automatically generated from src/transformers/models/qwen3_5/modular_qwen3_5.py.
3
+ # Do NOT edit this file manually as any edits will be overwritten by the generation of
4
+ # the file from the modular. If any change should be done, please apply the change to the
5
+ # modular_qwen3_5.py file directly. One of our CI enforces this.
6
+ # 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
7
+ # Copyright 2025 The Qwen Team and The HuggingFace Inc. team. All rights reserved.
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+
21
+ import itertools
22
+ import warnings
23
+ from collections.abc import Callable
24
+ from dataclasses import dataclass
25
+ from typing import Any, Optional
26
+
27
+ import torch
28
+ import torch.nn.functional as F
29
+ from torch import nn
30
+
31
+ from ... import initialization as init
32
+ from ...activations import ACT2FN
33
+ from ...cache_utils import Cache, DynamicCache
34
+ from ...generation import GenerationMixin
35
+ from ...integrations import use_kernelized_func
36
+ from ...masking_utils import create_causal_mask
37
+ from ...modeling_flash_attention_utils import FlashAttentionKwargs
38
+ from ...modeling_layers import (
39
+ GenericForSequenceClassification,
40
+ GenericForTokenClassification,
41
+ GradientCheckpointingLayer,
42
+ )
43
+ from ...modeling_outputs import (
44
+ BaseModelOutputWithPast,
45
+ BaseModelOutputWithPooling,
46
+ CausalLMOutputWithPast,
47
+ ModelOutput,
48
+ SequenceClassifierOutputWithPast,
49
+ )
50
+ from ...modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
51
+ from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
52
+ from ...processing_utils import Unpack
53
+ from ...utils import TransformersKwargs, auto_docstring, can_return_tuple, logging, torch_compilable_check
54
+ from ...utils.generic import (
55
+ accepts_precomputed_kwargs,
56
+ is_flash_attention_requested,
57
+ maybe_autocast,
58
+ merge_with_config_defaults,
59
+ )
60
+ from ...utils.import_utils import is_causal_conv1d_available, is_flash_linear_attention_available
61
+ from ...utils.output_capturing import capture_outputs
62
+ from ...vision_utils import get_vision_bilinear_indices_and_weights, get_vision_cu_seqlens, get_vision_position_ids
63
+ from .configuration_qwen3_5 import Qwen3_5Config, Qwen3_5TextConfig, Qwen3_5VisionConfig
64
+
65
+
66
+ if is_causal_conv1d_available():
67
+ from causal_conv1d import causal_conv1d_fn, causal_conv1d_update
68
+ else:
69
+ causal_conv1d_update, causal_conv1d_fn = None, None
70
+
71
+ if is_flash_linear_attention_available():
72
+ from fla.modules import FusedRMSNormGated
73
+ from fla.ops.gated_delta_rule import chunk_gated_delta_rule, fused_recurrent_gated_delta_rule
74
+ else:
75
+ chunk_gated_delta_rule, fused_recurrent_gated_delta_rule = None, None
76
+ FusedRMSNormGated = None
77
+
78
+ logger = logging.get_logger(__name__)
79
+
80
+
81
+ class Qwen3_5VisionRotaryEmbedding(nn.Module):
82
+ inv_freq: torch.Tensor # fix linting for `register_buffer`
83
+
84
+ def __init__(self, dim: int, theta: float = 10000.0) -> None:
85
+ super().__init__()
86
+ self.dim = dim
87
+ self.theta = theta
88
+ inv_freq = 1.0 / (theta ** (torch.arange(0, dim, 2, dtype=torch.float) / dim))
89
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
90
+
91
+ def forward(self, position_ids: torch.Tensor) -> torch.Tensor:
92
+ return (position_ids.unsqueeze(-1) * self.inv_freq).flatten(1)
93
+
94
+
95
+ class Qwen3_5TextRotaryEmbedding(nn.Module):
96
+ inv_freq: torch.Tensor # fix linting for `register_buffer`
97
+
98
+ def __init__(self, config: Qwen3_5TextConfig, device=None):
99
+ super().__init__()
100
+ self.max_seq_len_cached = config.max_position_embeddings
101
+ self.original_max_seq_len = config.max_position_embeddings
102
+
103
+ self.config = config
104
+
105
+ self.rope_type = self.config.rope_parameters["rope_type"]
106
+ rope_init_fn: Callable = self.compute_default_rope_parameters
107
+ if self.rope_type != "default":
108
+ rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
109
+ inv_freq, self.attention_scaling = rope_init_fn(self.config, device)
110
+
111
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
112
+ self.register_buffer("original_inv_freq", inv_freq.clone(), persistent=False)
113
+ self.mrope_section = config.rope_parameters.get("mrope_section", [11, 11, 10])
114
+
115
+ @staticmethod
116
+ def compute_default_rope_parameters(
117
+ config: Qwen3_5TextConfig | None = None,
118
+ device: Optional["torch.device"] = None,
119
+ seq_len: int | None = None,
120
+ ) -> tuple["torch.Tensor", float]:
121
+ """
122
+ Computes the inverse frequencies according to the original RoPE implementation
123
+ Args:
124
+ config ([`~transformers.PreTrainedConfig`]):
125
+ The model configuration.
126
+ device (`torch.device`):
127
+ The device to use for initialization of the inverse frequencies.
128
+ seq_len (`int`, *optional*):
129
+ The current sequence length. Unused for this type of RoPE.
130
+ Returns:
131
+ Tuple of (`torch.Tensor`, `float`), containing the inverse frequencies for the RoPE embeddings and the
132
+ post-processing scaling factor applied to the computed cos/sin (unused in this type of RoPE).
133
+ """
134
+ base = config.rope_parameters["rope_theta"]
135
+ partial_rotary_factor = config.rope_parameters.get("partial_rotary_factor", 1.0)
136
+ head_dim = getattr(config, "head_dim", None) or config.hidden_size // config.num_attention_heads
137
+ dim = int(head_dim * partial_rotary_factor)
138
+
139
+ attention_factor = 1.0 # Unused in this type of RoPE
140
+
141
+ # Compute the inverse frequencies
142
+ inv_freq = 1.0 / (
143
+ base ** (torch.arange(0, dim, 2, dtype=torch.int64).to(device=device, dtype=torch.float) / dim)
144
+ )
145
+ return inv_freq, attention_factor
146
+
147
+ @torch.no_grad()
148
+ @dynamic_rope_update # power user: used with advanced RoPE types (e.g. dynamic rope)
149
+ def forward(self, x, position_ids):
150
+ # In contrast to other models, Qwen3_5 has different position ids for the grids
151
+ # So we expand the inv_freq to shape (3, ...)
152
+ if position_ids.ndim == 2:
153
+ position_ids = position_ids[None, ...].expand(3, position_ids.shape[0], -1)
154
+ inv_freq_expanded = (
155
+ self.inv_freq[None, None, :, None].float().expand(3, position_ids.shape[1], -1, 1).to(x.device)
156
+ )
157
+ position_ids_expanded = position_ids[:, :, None, :].float() # shape (3, bs, 1, positions)
158
+
159
+ device_type = x.device.type if isinstance(x.device.type, str) and x.device.type != "mps" else "cpu"
160
+ with maybe_autocast(device_type=device_type, enabled=False): # Force float32
161
+ freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(2, 3)
162
+ freqs = self.apply_interleaved_mrope(freqs, self.mrope_section)
163
+ emb = torch.cat((freqs, freqs), dim=-1)
164
+ cos = emb.cos() * self.attention_scaling
165
+ sin = emb.sin() * self.attention_scaling
166
+
167
+ return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
168
+
169
+ def apply_interleaved_mrope(self, freqs, mrope_section):
170
+ """Apply interleaved MRoPE to 3D rotary embeddings.
171
+ Reorganizes frequency layout from chunked [TTT...HHH...WWW] to
172
+ interleaved [THWTHWTHW...TT], preserving frequency continuity.
173
+ args:
174
+ x: (3, bs, seq_len, head_dim // 2)
175
+ mrope_section: (3,)
176
+ returns:
177
+ x_t: (bs, seq_len, head_dim // 2)
178
+ """
179
+ freqs_t = freqs[0] # just overwrite the first dimension T
180
+ for dim, offset in enumerate((1, 2), start=1): # H, W
181
+ length = mrope_section[dim] * 3
182
+ idx = slice(offset, length, 3)
183
+ freqs_t[..., idx] = freqs[dim, ..., idx]
184
+ return freqs_t
185
+
186
+
187
+ class Qwen3_5RMSNormGated(nn.Module):
188
+ def __init__(self, hidden_size, eps=1e-6, **kwargs):
189
+ super().__init__()
190
+ self.weight = nn.Parameter(torch.ones(hidden_size))
191
+ self.variance_epsilon = eps
192
+
193
+ def forward(self, hidden_states, gate=None):
194
+ input_dtype = hidden_states.dtype
195
+ hidden_states = hidden_states.to(torch.float32)
196
+ variance = hidden_states.pow(2).mean(-1, keepdim=True)
197
+ # Norm before gate
198
+ hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
199
+ hidden_states = self.weight * hidden_states.to(input_dtype)
200
+ hidden_states = hidden_states * F.silu(gate.to(torch.float32))
201
+
202
+ return hidden_states.to(input_dtype)
203
+
204
+
205
+ def apply_mask_to_padding_states(hidden_states, attention_mask):
206
+ """
207
+ Tunes out the hidden states for padding tokens, see https://github.com/state-spaces/mamba/issues/66
208
+ """
209
+ # NOTE: attention mask is a 2D boolean tensor
210
+ if attention_mask is not None and attention_mask.shape[1] > 1 and attention_mask.shape[0] > 1:
211
+ dtype = hidden_states.dtype
212
+ hidden_states = (hidden_states * attention_mask[:, :, None]).to(dtype)
213
+
214
+ return hidden_states
215
+
216
+
217
+ is_fast_path_available = all(
218
+ (causal_conv1d_fn, causal_conv1d_update, chunk_gated_delta_rule, fused_recurrent_gated_delta_rule)
219
+ )
220
+
221
+
222
+ def torch_causal_conv1d_update(
223
+ hidden_states,
224
+ conv_state,
225
+ weight,
226
+ bias=None,
227
+ activation=None,
228
+ ):
229
+ _, hidden_size, seq_len = hidden_states.shape
230
+ state_len = conv_state.shape[-1]
231
+
232
+ hidden_states_new = torch.cat([conv_state, hidden_states], dim=-1).to(weight.dtype)
233
+ conv_state.copy_(hidden_states_new[:, :, -state_len:])
234
+ out = F.conv1d(hidden_states_new, weight.unsqueeze(1), bias, padding=0, groups=hidden_size)
235
+ out = F.silu(out[:, :, -seq_len:])
236
+ out = out.to(hidden_states.dtype)
237
+ return out
238
+
239
+
240
+ def l2norm(x: torch.FloatTensor, dim: int = -1, eps: float = 1e-6):
241
+ """This function is intended to align with the l2norm implementation in the FLA library."""
242
+ inv_norm = torch.rsqrt((x * x).sum(dim=dim, keepdim=True) + eps)
243
+ return x * inv_norm
244
+
245
+
246
+ def torch_chunk_gated_delta_rule(
247
+ query,
248
+ key,
249
+ value,
250
+ g,
251
+ beta,
252
+ chunk_size=64,
253
+ initial_state=None,
254
+ output_final_state=False,
255
+ use_qk_l2norm_in_kernel=False,
256
+ **kwargs,
257
+ ):
258
+ initial_dtype = query.dtype
259
+ if use_qk_l2norm_in_kernel:
260
+ query = l2norm(query, dim=-1, eps=1e-6)
261
+ key = l2norm(key, dim=-1, eps=1e-6)
262
+ query, key, value, beta, g = [
263
+ x.transpose(1, 2).contiguous().to(torch.float32) for x in (query, key, value, beta, g)
264
+ ]
265
+
266
+ batch_size, num_heads, sequence_length, k_head_dim = key.shape
267
+ v_head_dim = value.shape[-1]
268
+ pad_size = (chunk_size - sequence_length % chunk_size) % chunk_size
269
+ query = F.pad(query, (0, 0, 0, pad_size))
270
+ key = F.pad(key, (0, 0, 0, pad_size))
271
+ value = F.pad(value, (0, 0, 0, pad_size))
272
+ beta = F.pad(beta, (0, pad_size))
273
+ g = F.pad(g, (0, pad_size))
274
+ total_sequence_length = sequence_length + pad_size
275
+ scale = 1 / (query.shape[-1] ** 0.5)
276
+ query = query * scale
277
+
278
+ v_beta = value * beta.unsqueeze(-1)
279
+ k_beta = key * beta.unsqueeze(-1)
280
+ # reshape to chunks
281
+ query, key, value, k_beta, v_beta = [
282
+ x.reshape(x.shape[0], x.shape[1], -1, chunk_size, x.shape[-1]) for x in (query, key, value, k_beta, v_beta)
283
+ ]
284
+ g = g.reshape(g.shape[0], g.shape[1], -1, chunk_size)
285
+ mask = torch.triu(torch.ones(chunk_size, chunk_size, dtype=torch.bool, device=query.device), diagonal=0)
286
+
287
+ # chunk decay
288
+ g = g.cumsum(dim=-1)
289
+ decay_mask = ((g.unsqueeze(-1) - g.unsqueeze(-2)).tril().exp().float()).tril()
290
+ attn = -((k_beta @ key.transpose(-1, -2)) * decay_mask).masked_fill(mask, 0)
291
+ for i in range(1, chunk_size):
292
+ row = attn[..., i, :i].clone()
293
+ sub = attn[..., :i, :i].clone()
294
+ attn[..., i, :i] = row + (row.unsqueeze(-1) * sub).sum(-2)
295
+ attn = attn + torch.eye(chunk_size, dtype=attn.dtype, device=attn.device)
296
+ value = attn @ v_beta
297
+ k_cumdecay = attn @ (k_beta * g.exp().unsqueeze(-1))
298
+ last_recurrent_state = (
299
+ torch.zeros(batch_size, num_heads, k_head_dim, v_head_dim, dtype=value.dtype, device=value.device)
300
+ if initial_state is None
301
+ else initial_state.to(value)
302
+ )
303
+ core_attn_out = torch.zeros_like(value)
304
+ mask = torch.triu(torch.ones(chunk_size, chunk_size, dtype=torch.bool, device=query.device), diagonal=1)
305
+
306
+ # for each chunk
307
+ for i in range(0, total_sequence_length // chunk_size):
308
+ q_i, k_i, v_i = query[:, :, i], key[:, :, i], value[:, :, i]
309
+ attn = q_i @ k_i.transpose(-1, -2) * decay_mask[:, :, i]
310
+ v_prime = (k_cumdecay[:, :, i]) @ last_recurrent_state
311
+ v_new = v_i - v_prime
312
+ attn_inter = (q_i * g[:, :, i, :, None].exp()) @ last_recurrent_state
313
+ core_attn_out[:, :, i] = attn_inter + attn @ v_new
314
+ last_recurrent_state = (
315
+ last_recurrent_state * g[:, :, i, -1, None, None].exp()
316
+ + (k_i * (g[:, :, i, -1, None] - g[:, :, i]).exp()[..., None]).transpose(-1, -2) @ v_new
317
+ )
318
+
319
+ if not output_final_state:
320
+ last_recurrent_state = None
321
+ core_attn_out = core_attn_out.reshape(core_attn_out.shape[0], core_attn_out.shape[1], -1, core_attn_out.shape[-1])
322
+ core_attn_out = core_attn_out[:, :, :sequence_length]
323
+ core_attn_out = core_attn_out.transpose(1, 2).contiguous().to(initial_dtype)
324
+ return core_attn_out, last_recurrent_state
325
+
326
+
327
+ def torch_recurrent_gated_delta_rule(
328
+ query, key, value, g, beta, initial_state, output_final_state, use_qk_l2norm_in_kernel=False
329
+ ):
330
+ initial_dtype = query.dtype
331
+ if use_qk_l2norm_in_kernel:
332
+ query = l2norm(query, dim=-1, eps=1e-6)
333
+ key = l2norm(key, dim=-1, eps=1e-6)
334
+ query, key, value, beta, g = [
335
+ x.transpose(1, 2).contiguous().to(torch.float32) for x in (query, key, value, beta, g)
336
+ ]
337
+
338
+ batch_size, num_heads, sequence_length, k_head_dim = key.shape
339
+ v_head_dim = value.shape[-1]
340
+ scale = 1 / (query.shape[-1] ** 0.5)
341
+ query = query * scale
342
+
343
+ core_attn_out = torch.zeros(
344
+ batch_size, num_heads, sequence_length, v_head_dim, dtype=value.dtype, device=value.device
345
+ )
346
+ last_recurrent_state = (
347
+ torch.zeros(batch_size, num_heads, k_head_dim, v_head_dim, dtype=value.dtype, device=value.device)
348
+ if initial_state is None
349
+ else initial_state.to(value)
350
+ )
351
+
352
+ for i in range(sequence_length):
353
+ q_t = query[:, :, i]
354
+ k_t = key[:, :, i]
355
+ v_t = value[:, :, i]
356
+ g_t = g[:, :, i].exp().unsqueeze(-1).unsqueeze(-1)
357
+ beta_t = beta[:, :, i].unsqueeze(-1)
358
+
359
+ last_recurrent_state = last_recurrent_state * g_t
360
+ kv_mem = (last_recurrent_state * k_t.unsqueeze(-1)).sum(dim=-2)
361
+ delta = (v_t - kv_mem) * beta_t
362
+ last_recurrent_state = last_recurrent_state + k_t.unsqueeze(-1) * delta.unsqueeze(-2)
363
+ core_attn_out[:, :, i] = (last_recurrent_state * q_t.unsqueeze(-1)).sum(dim=-2)
364
+
365
+ if not output_final_state:
366
+ last_recurrent_state = None
367
+ core_attn_out = core_attn_out.transpose(1, 2).contiguous().to(initial_dtype)
368
+ return core_attn_out, last_recurrent_state
369
+
370
+
371
+ class Qwen3_5GatedDeltaNet(nn.Module):
372
+ def __init__(self, config: Qwen3_5Config, layer_idx: int):
373
+ super().__init__()
374
+ self.hidden_size = config.hidden_size
375
+ self.num_v_heads = config.linear_num_value_heads
376
+ self.num_k_heads = config.linear_num_key_heads
377
+ self.head_k_dim = config.linear_key_head_dim
378
+ self.head_v_dim = config.linear_value_head_dim
379
+ self.key_dim = self.head_k_dim * self.num_k_heads
380
+ self.value_dim = self.head_v_dim * self.num_v_heads
381
+
382
+ self.conv_kernel_size = config.linear_conv_kernel_dim
383
+ self.layer_idx = layer_idx
384
+ self.activation = config.hidden_act
385
+ self.act = ACT2FN[config.hidden_act]
386
+ self.layer_norm_epsilon = config.rms_norm_eps
387
+
388
+ # QKV
389
+ self.conv_dim = self.key_dim * 2 + self.value_dim
390
+ self.conv1d = nn.Conv1d(
391
+ in_channels=self.conv_dim,
392
+ out_channels=self.conv_dim,
393
+ bias=False,
394
+ kernel_size=self.conv_kernel_size,
395
+ groups=self.conv_dim,
396
+ padding=self.conv_kernel_size - 1,
397
+ )
398
+
399
+ # time step projection (discretization)
400
+ # instantiate once and copy inv_dt in init_weights of PretrainedModel
401
+ self.dt_bias = nn.Parameter(torch.ones(self.num_v_heads))
402
+
403
+ A = torch.empty(self.num_v_heads).uniform_(0, 16)
404
+ self.A_log = nn.Parameter(torch.log(A))
405
+
406
+ self.norm = (
407
+ Qwen3_5RMSNormGated(self.head_v_dim, eps=self.layer_norm_epsilon)
408
+ if FusedRMSNormGated is None
409
+ else FusedRMSNormGated(
410
+ self.head_v_dim,
411
+ eps=self.layer_norm_epsilon,
412
+ activation=self.activation,
413
+ device=torch.cuda.current_device(),
414
+ dtype=config.dtype if config.dtype is not None else torch.get_default_dtype(),
415
+ )
416
+ )
417
+
418
+ self.out_proj = nn.Linear(self.value_dim, self.hidden_size, bias=False)
419
+
420
+ self.causal_conv1d_fn = causal_conv1d_fn
421
+ self.causal_conv1d_update = causal_conv1d_update or torch_causal_conv1d_update
422
+ self.chunk_gated_delta_rule = chunk_gated_delta_rule or torch_chunk_gated_delta_rule
423
+ self.recurrent_gated_delta_rule = fused_recurrent_gated_delta_rule or torch_recurrent_gated_delta_rule
424
+
425
+ if not is_fast_path_available:
426
+ logger.warning_once(
427
+ "The fast path is not available because one of the required library is not installed. Falling back to "
428
+ "torch implementation. To install follow https://github.com/fla-org/flash-linear-attention#installation and"
429
+ " https://github.com/Dao-AILab/causal-conv1d"
430
+ )
431
+
432
+ self.in_proj_qkv = nn.Linear(self.hidden_size, self.key_dim * 2 + self.value_dim, bias=False)
433
+ self.in_proj_z = nn.Linear(self.hidden_size, self.value_dim, bias=False)
434
+ self.in_proj_b = nn.Linear(self.hidden_size, self.num_v_heads, bias=False)
435
+ self.in_proj_a = nn.Linear(self.hidden_size, self.num_v_heads, bias=False)
436
+
437
+ def forward(
438
+ self,
439
+ hidden_states: torch.Tensor,
440
+ cache_params: Cache | None = None,
441
+ attention_mask: torch.Tensor | None = None,
442
+ **kwargs: Unpack[TransformersKwargs],
443
+ ):
444
+ hidden_states = apply_mask_to_padding_states(hidden_states, attention_mask)
445
+
446
+ # Set up dimensions for reshapes later
447
+ batch_size, seq_len, _ = hidden_states.shape
448
+
449
+ # We have cached `conv_state` / `recurrent_state` to continue from. The two cached modes
450
+ # (single-token decode and chunk-tokens continuation) share the state read here; they only
451
+ # diverge in how the conv input is assembled and which kernel consumes the states below,
452
+ # which we gate locally on `seq_len`.
453
+ use_precomputed_states = cache_params is not None and cache_params.has_previous_state(self.layer_idx)
454
+
455
+ # getting projected states from cache if it exists
456
+ if use_precomputed_states:
457
+ conv_state = cache_params.layers[self.layer_idx].conv_states
458
+ recurrent_state = cache_params.layers[self.layer_idx].recurrent_states
459
+
460
+ mixed_qkv = self.in_proj_qkv(hidden_states)
461
+ mixed_qkv = mixed_qkv.transpose(1, 2)
462
+
463
+ z = self.in_proj_z(hidden_states)
464
+ z = z.reshape(batch_size, seq_len, -1, self.head_v_dim)
465
+
466
+ b = self.in_proj_b(hidden_states)
467
+ a = self.in_proj_a(hidden_states)
468
+
469
+ if use_precomputed_states and seq_len == 1:
470
+ # Single-token cached decode: the fused per-step kernel updates the conv state in-place.
471
+ mixed_qkv = self.causal_conv1d_update(
472
+ mixed_qkv,
473
+ conv_state,
474
+ self.conv1d.weight.squeeze(1),
475
+ self.conv1d.bias,
476
+ self.activation,
477
+ )
478
+ else:
479
+ # Multi-token forward (prefill, or chunked-tokens decode when the cache has prior state).
480
+ if use_precomputed_states:
481
+ # Cached chunked-tokens decode: prepend the cached conv context so the causal conv
482
+ # sees the correct left-context rather than zero-padding. Dropped from the output
483
+ # at the end of this branch.
484
+ mixed_qkv = torch.cat([conv_state, mixed_qkv], dim=-1)
485
+ if cache_params is not None:
486
+ new_conv_state = F.pad(mixed_qkv, (self.conv_kernel_size - mixed_qkv.shape[-1], 0))
487
+ cache_params.update_conv_state(new_conv_state, self.layer_idx)
488
+ if self.causal_conv1d_fn is not None:
489
+ mixed_qkv = self.causal_conv1d_fn(
490
+ x=mixed_qkv,
491
+ weight=self.conv1d.weight.squeeze(1),
492
+ bias=self.conv1d.bias,
493
+ activation=self.activation,
494
+ seq_idx=kwargs.get("seq_idx"),
495
+ )
496
+ else:
497
+ mixed_qkv = F.silu(self.conv1d(mixed_qkv)[:, :, : mixed_qkv.shape[-1]])
498
+ if use_precomputed_states:
499
+ mixed_qkv = mixed_qkv[:, :, -seq_len:]
500
+
501
+ mixed_qkv = mixed_qkv.transpose(1, 2)
502
+ query, key, value = torch.split(
503
+ mixed_qkv,
504
+ [
505
+ self.key_dim,
506
+ self.key_dim,
507
+ self.value_dim,
508
+ ],
509
+ dim=-1,
510
+ )
511
+
512
+ query = query.reshape(batch_size, seq_len, -1, self.head_k_dim)
513
+ key = key.reshape(batch_size, seq_len, -1, self.head_k_dim)
514
+ value = value.reshape(batch_size, seq_len, -1, self.head_v_dim)
515
+
516
+ beta = b.sigmoid()
517
+ # If the model is loaded in fp16, without the .float() here, A might be -inf
518
+ g = -self.A_log.float().exp() * F.softplus(a.float() + self.dt_bias)
519
+ if self.num_v_heads // self.num_k_heads > 1:
520
+ query = query.repeat_interleave(self.num_v_heads // self.num_k_heads, dim=2)
521
+ key = key.repeat_interleave(self.num_v_heads // self.num_k_heads, dim=2)
522
+
523
+ if use_precomputed_states and seq_len == 1:
524
+ core_attn_out, last_recurrent_state = self.recurrent_gated_delta_rule(
525
+ query,
526
+ key,
527
+ value,
528
+ g=g,
529
+ beta=beta,
530
+ initial_state=recurrent_state,
531
+ output_final_state=cache_params is not None,
532
+ use_qk_l2norm_in_kernel=True,
533
+ )
534
+ else:
535
+ core_attn_out, last_recurrent_state = self.chunk_gated_delta_rule(
536
+ query,
537
+ key,
538
+ value,
539
+ g=g,
540
+ beta=beta,
541
+ initial_state=recurrent_state if use_precomputed_states else None,
542
+ output_final_state=cache_params is not None,
543
+ use_qk_l2norm_in_kernel=True,
544
+ # The chunked FLA kernel takes a single `cu_seqlens` arg; for packed self-attention this matches q-side lengths.
545
+ cu_seqlens=kwargs.get("cu_seq_lens_q"),
546
+ )
547
+
548
+ # Update cache
549
+ if cache_params is not None:
550
+ cache_params.update_recurrent_state(last_recurrent_state, self.layer_idx)
551
+
552
+ # reshape input data into 2D tensor
553
+ core_attn_out = core_attn_out.reshape(-1, self.head_v_dim)
554
+ z = z.reshape(-1, self.head_v_dim)
555
+ core_attn_out = self.norm(core_attn_out, z)
556
+ core_attn_out = core_attn_out.reshape(batch_size, seq_len, -1)
557
+
558
+ output = self.out_proj(core_attn_out)
559
+ return output
560
+
561
+
562
+ def rotate_half(x):
563
+ """Rotates half the hidden dims of the input."""
564
+ x1 = x[..., : x.shape[-1] // 2]
565
+ x2 = x[..., x.shape[-1] // 2 :]
566
+ return torch.cat((-x2, x1), dim=-1)
567
+
568
+
569
+ # Adapted from transformers.models.glm.modular_glm.apply_rotary_pos_emb
570
+ def apply_rotary_pos_emb(q, k, cos, sin, unsqueeze_dim=1):
571
+ """Applies Rotary Position Embedding to the query and key tensors.
572
+
573
+ Removes the interleaving of cos and sin from GLM
574
+
575
+ Args:
576
+ q (`torch.Tensor`): The query tensor.
577
+ k (`torch.Tensor`): The key tensor.
578
+ cos (`torch.Tensor`): The cosine part of the rotary embedding.
579
+ sin (`torch.Tensor`): The sine part of the rotary embedding.
580
+ unsqueeze_dim (`int`, *optional*, defaults to 1):
581
+ The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
582
+ sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
583
+ that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
584
+ k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
585
+ cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
586
+ the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
587
+ Returns:
588
+ `tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
589
+ """
590
+ cos = cos.unsqueeze(unsqueeze_dim)
591
+ sin = sin.unsqueeze(unsqueeze_dim)
592
+
593
+ # Keep half or full tensor for later concatenation
594
+ rotary_dim = cos.shape[-1]
595
+ q_rot, q_pass = q[..., :rotary_dim], q[..., rotary_dim:]
596
+ k_rot, k_pass = k[..., :rotary_dim], k[..., rotary_dim:]
597
+
598
+ # Apply rotary embeddings on the first half or full tensor
599
+ q_embed = (q_rot * cos) + (rotate_half(q_rot) * sin)
600
+ k_embed = (k_rot * cos) + (rotate_half(k_rot) * sin)
601
+
602
+ # Concatenate back to full shape
603
+ q_embed = torch.cat([q_embed, q_pass], dim=-1)
604
+ k_embed = torch.cat([k_embed, k_pass], dim=-1)
605
+ return q_embed, k_embed
606
+
607
+
608
+ def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
609
+ """
610
+ This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
611
+ num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
612
+ """
613
+ batch, num_key_value_heads, slen, head_dim = hidden_states.shape
614
+ if n_rep == 1:
615
+ return hidden_states
616
+ hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
617
+ return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
618
+
619
+
620
+ def eager_attention_forward(
621
+ module: nn.Module,
622
+ query: torch.Tensor,
623
+ key: torch.Tensor,
624
+ value: torch.Tensor,
625
+ attention_mask: torch.Tensor | None,
626
+ scaling: float,
627
+ dropout: float = 0.0,
628
+ **kwargs: Unpack[TransformersKwargs],
629
+ ):
630
+ key_states = repeat_kv(key, module.num_key_value_groups)
631
+ value_states = repeat_kv(value, module.num_key_value_groups)
632
+
633
+ attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
634
+ if attention_mask is not None:
635
+ attn_weights = attn_weights + attention_mask
636
+
637
+ attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
638
+ attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
639
+ attn_output = torch.matmul(attn_weights, value_states)
640
+ attn_output = attn_output.transpose(1, 2).contiguous()
641
+
642
+ return attn_output, attn_weights
643
+
644
+
645
+ @use_kernelized_func(apply_rotary_pos_emb)
646
+ class Qwen3_5Attention(nn.Module):
647
+ """Multi-headed attention from 'Attention Is All You Need' paper"""
648
+
649
+ def __init__(self, config: Qwen3_5Config, layer_idx: int):
650
+ super().__init__()
651
+ self.config = config
652
+ self.layer_idx = layer_idx
653
+ self.head_dim = getattr(config, "head_dim", config.hidden_size // config.num_attention_heads)
654
+ self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
655
+ self.scaling = self.head_dim**-0.5
656
+ self.attention_dropout = config.attention_dropout
657
+ self.is_causal = True
658
+ self.q_proj = nn.Linear(
659
+ config.hidden_size, config.num_attention_heads * self.head_dim * 2, bias=config.attention_bias
660
+ )
661
+ self.k_proj = nn.Linear(
662
+ config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
663
+ )
664
+ self.v_proj = nn.Linear(
665
+ config.hidden_size, config.num_key_value_heads * self.head_dim, bias=config.attention_bias
666
+ )
667
+ self.o_proj = nn.Linear(
668
+ config.num_attention_heads * self.head_dim, config.hidden_size, bias=config.attention_bias
669
+ )
670
+ self.q_norm = Qwen3_5RMSNorm(self.head_dim, eps=config.rms_norm_eps) # unlike olmo, only on the head dim!
671
+ self.k_norm = Qwen3_5RMSNorm(self.head_dim, eps=config.rms_norm_eps) # thus post q_norm does not need reshape
672
+
673
+ def forward(
674
+ self,
675
+ hidden_states: torch.Tensor,
676
+ position_embeddings: tuple[torch.Tensor, torch.Tensor],
677
+ attention_mask: torch.Tensor | None,
678
+ past_key_values: Cache | None = None,
679
+ **kwargs: Unpack[FlashAttentionKwargs],
680
+ ) -> tuple[torch.Tensor, torch.Tensor | None]:
681
+ input_shape = hidden_states.shape[:-1]
682
+ hidden_shape = (*input_shape, -1, self.head_dim)
683
+
684
+ query_states, gate = torch.chunk(
685
+ self.q_proj(hidden_states).view(*input_shape, -1, self.head_dim * 2), 2, dim=-1
686
+ )
687
+ gate = gate.reshape(*input_shape, -1)
688
+
689
+ query_states = self.q_norm(query_states.view(hidden_shape)).transpose(1, 2)
690
+ key_states = self.k_norm(self.k_proj(hidden_states).view(hidden_shape)).transpose(1, 2)
691
+ value_states = self.v_proj(hidden_states).view(hidden_shape).transpose(1, 2)
692
+
693
+ cos, sin = position_embeddings
694
+ query_states, key_states = apply_rotary_pos_emb(query_states, key_states, cos, sin)
695
+
696
+ if past_key_values is not None:
697
+ key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx)
698
+
699
+ attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
700
+ self.config._attn_implementation, eager_attention_forward
701
+ )
702
+
703
+ attn_output, attn_weights = attention_interface(
704
+ self,
705
+ query_states,
706
+ key_states,
707
+ value_states,
708
+ attention_mask,
709
+ dropout=0.0 if not self.training else self.attention_dropout,
710
+ scaling=self.scaling,
711
+ **kwargs,
712
+ )
713
+
714
+ attn_output = attn_output.reshape(*input_shape, -1).contiguous()
715
+ attn_output = attn_output * torch.sigmoid(gate)
716
+
717
+ attn_output = self.o_proj(attn_output)
718
+ return attn_output, attn_weights
719
+
720
+
721
+ class Qwen3_5MLP(nn.Module):
722
+ def __init__(self, config: Qwen3_5Config, intermediate_size: int):
723
+ super().__init__()
724
+ self.config = config
725
+ self.hidden_size = config.hidden_size
726
+ self.intermediate_size = intermediate_size
727
+ self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
728
+ self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
729
+ self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
730
+ self.act_fn = ACT2FN[config.hidden_act]
731
+
732
+ def forward(self, x):
733
+ down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
734
+ return down_proj
735
+
736
+
737
+ class Qwen3_5RMSNorm(nn.Module):
738
+ def __init__(self, dim: int, eps: float = 1e-6):
739
+ super().__init__()
740
+ self.eps = eps
741
+ self.weight = nn.Parameter(torch.zeros(dim))
742
+
743
+ def _norm(self, x):
744
+ return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
745
+
746
+ def forward(self, x):
747
+ output = self._norm(x.float())
748
+ # Llama does x.to(float16) * w whilst Qwen3_5 is (x * w).to(float16)
749
+ # See https://github.com/huggingface/transformers/pull/29402
750
+ output = output * (1.0 + self.weight.float())
751
+ return output.type_as(x)
752
+
753
+ def extra_repr(self):
754
+ return f"{tuple(self.weight.shape)}, eps={self.eps}"
755
+
756
+
757
+ class Qwen3_5DecoderLayer(GradientCheckpointingLayer):
758
+ def __init__(self, config: Qwen3_5TextConfig, layer_idx: int):
759
+ super().__init__()
760
+ self.hidden_size = config.hidden_size
761
+ self.layer_type = config.layer_types[layer_idx]
762
+ if self.layer_type == "linear_attention":
763
+ self.linear_attn = Qwen3_5GatedDeltaNet(config, layer_idx)
764
+ elif self.layer_type == "full_attention":
765
+ self.self_attn = Qwen3_5Attention(config, layer_idx)
766
+ self.mlp = Qwen3_5MLP(config, config.intermediate_size)
767
+ self.input_layernorm = Qwen3_5RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
768
+ self.post_attention_layernorm = Qwen3_5RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
769
+
770
+ def forward(
771
+ self,
772
+ hidden_states: torch.Tensor,
773
+ position_embeddings: tuple[torch.Tensor, torch.Tensor],
774
+ attention_mask: torch.Tensor | None = None,
775
+ position_ids: torch.LongTensor | None = None,
776
+ past_key_values: Cache | None = None,
777
+ **kwargs: Unpack[TransformersKwargs],
778
+ ) -> torch.FloatTensor:
779
+ residual = hidden_states
780
+
781
+ hidden_states = self.input_layernorm(hidden_states)
782
+
783
+ # Token Mixer
784
+ if self.layer_type == "linear_attention":
785
+ hidden_states = self.linear_attn(
786
+ hidden_states=hidden_states,
787
+ cache_params=past_key_values,
788
+ attention_mask=attention_mask,
789
+ **kwargs,
790
+ )
791
+ elif self.layer_type == "full_attention":
792
+ # Self Attention
793
+ hidden_states, _ = self.self_attn(
794
+ hidden_states=hidden_states,
795
+ attention_mask=attention_mask,
796
+ position_ids=position_ids,
797
+ past_key_values=past_key_values,
798
+ position_embeddings=position_embeddings,
799
+ **kwargs,
800
+ )
801
+
802
+ hidden_states = residual + hidden_states
803
+
804
+ # Fully Connected
805
+ residual = hidden_states
806
+ hidden_states = self.post_attention_layernorm(hidden_states)
807
+ hidden_states = self.mlp(hidden_states)
808
+ hidden_states = residual + hidden_states
809
+
810
+ return hidden_states
811
+
812
+
813
+ class Qwen3_5PreTrainedModel(PreTrainedModel):
814
+ config: Qwen3_5Config
815
+ base_model_prefix = "model"
816
+ supports_gradient_checkpointing = True
817
+ _no_split_modules = ["Qwen3_5DecoderLayer", "Qwen3_5VisionBlock"]
818
+ _skip_keys_device_placement = ["past_key_values"]
819
+ _supports_flash_attn = True
820
+ _supports_sdpa = True
821
+ _keys_to_ignore_on_load_unexpected = [r"^mtp.*"]
822
+ _can_record_outputs = {
823
+ "hidden_states": Qwen3_5DecoderLayer,
824
+ "attentions": Qwen3_5Attention,
825
+ }
826
+ _is_stateful = True
827
+
828
+ @torch.no_grad()
829
+ def _init_weights(self, module):
830
+ super()._init_weights(module)
831
+ if isinstance(module, Qwen3_5GatedDeltaNet):
832
+ init.ones_(module.dt_bias)
833
+ init.copy_(module.A_log, torch.empty_like(module.A_log).uniform_(0, 16).log_())
834
+ # We initialize with 0s to be 1 centered as the RMSNorm here does (1 + weight)
835
+ elif isinstance(module, Qwen3_5RMSNorm):
836
+ init.zeros_(module.weight)
837
+ elif isinstance(module, Qwen3_5VisionRotaryEmbedding):
838
+ inv_freq = 1.0 / (module.theta ** (torch.arange(0, module.dim, 2, dtype=torch.float) / module.dim))
839
+ init.copy_(module.inv_freq, inv_freq)
840
+
841
+
842
+ class Qwen3_5VisionMLP(nn.Module):
843
+ def __init__(self, config):
844
+ super().__init__()
845
+ self.hidden_size = config.hidden_size
846
+ self.intermediate_size = config.intermediate_size
847
+ self.linear_fc1 = nn.Linear(self.hidden_size, self.intermediate_size, bias=True)
848
+ self.linear_fc2 = nn.Linear(self.intermediate_size, self.hidden_size, bias=True)
849
+ self.act_fn = ACT2FN[config.hidden_act]
850
+
851
+ def forward(self, hidden_state):
852
+ return self.linear_fc2(self.act_fn(self.linear_fc1(hidden_state)))
853
+
854
+
855
+ class Qwen3_5VisionPatchEmbed(nn.Module):
856
+ def __init__(self, config) -> None:
857
+ super().__init__()
858
+ self.patch_size = config.patch_size
859
+ self.temporal_patch_size = config.temporal_patch_size
860
+ self.in_channels = config.in_channels
861
+ self.embed_dim = config.hidden_size
862
+
863
+ kernel_size = [self.temporal_patch_size, self.patch_size, self.patch_size]
864
+ self.proj = nn.Conv3d(self.in_channels, self.embed_dim, kernel_size=kernel_size, stride=kernel_size, bias=True)
865
+
866
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
867
+ target_dtype = self.proj.weight.dtype
868
+ hidden_states = hidden_states.view(
869
+ -1, self.in_channels, self.temporal_patch_size, self.patch_size, self.patch_size
870
+ )
871
+ hidden_states = self.proj(hidden_states.to(dtype=target_dtype)).view(-1, self.embed_dim)
872
+ return hidden_states
873
+
874
+
875
+ class Qwen3_5VisionPatchMerger(nn.Module):
876
+ def __init__(self, config: Qwen3_5VisionConfig, use_postshuffle_norm=False) -> None:
877
+ super().__init__()
878
+ self.hidden_size = config.hidden_size * (config.spatial_merge_size**2)
879
+ self.use_postshuffle_norm = use_postshuffle_norm
880
+ self.norm = nn.LayerNorm(self.hidden_size if use_postshuffle_norm else config.hidden_size, eps=1e-6)
881
+ self.linear_fc1 = nn.Linear(self.hidden_size, self.hidden_size)
882
+ self.act_fn = nn.GELU()
883
+ self.linear_fc2 = nn.Linear(self.hidden_size, config.out_hidden_size)
884
+
885
+ def forward(self, x: torch.Tensor) -> torch.Tensor:
886
+ x = self.norm(x.view(-1, self.hidden_size) if self.use_postshuffle_norm else x).view(-1, self.hidden_size)
887
+ x = self.linear_fc2(self.act_fn(self.linear_fc1(x)))
888
+ return x
889
+
890
+
891
+ def apply_rotary_pos_emb_vision(
892
+ q: torch.Tensor, k: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor
893
+ ) -> tuple[torch.Tensor, torch.Tensor]:
894
+ orig_q_dtype = q.dtype
895
+ orig_k_dtype = k.dtype
896
+ q, k = q.float(), k.float()
897
+ cos, sin = cos.unsqueeze(-2).float(), sin.unsqueeze(-2).float()
898
+ q_embed = (q * cos) + (rotate_half(q) * sin)
899
+ k_embed = (k * cos) + (rotate_half(k) * sin)
900
+ q_embed = q_embed.to(orig_q_dtype)
901
+ k_embed = k_embed.to(orig_k_dtype)
902
+ return q_embed, k_embed
903
+
904
+
905
+ class Qwen3_5VisionAttention(nn.Module):
906
+ def __init__(self, config: Qwen3_5VisionConfig) -> None:
907
+ super().__init__()
908
+ self.dim = config.hidden_size
909
+ self.num_heads = config.num_heads
910
+ self.head_dim = self.dim // self.num_heads
911
+ self.num_key_value_groups = 1 # needed for eager attention
912
+ self.qkv = nn.Linear(self.dim, self.dim * 3, bias=True)
913
+ self.proj = nn.Linear(self.dim, self.dim)
914
+ self.scaling = self.head_dim**-0.5
915
+ self.config = config
916
+ self.attention_dropout = 0.0
917
+ self.is_causal = False
918
+
919
+ def forward(
920
+ self,
921
+ hidden_states: torch.Tensor,
922
+ cu_seqlens: torch.Tensor,
923
+ rotary_pos_emb: torch.Tensor | None = None,
924
+ position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
925
+ **kwargs,
926
+ ) -> torch.Tensor:
927
+ seq_length = hidden_states.shape[0]
928
+ query_states, key_states, value_states = (
929
+ self.qkv(hidden_states).reshape(seq_length, 3, self.num_heads, -1).permute(1, 0, 2, 3).unbind(0)
930
+ )
931
+ cos, sin = position_embeddings
932
+ query_states, key_states = apply_rotary_pos_emb_vision(query_states, key_states, cos, sin)
933
+
934
+ query_states = query_states.transpose(0, 1).unsqueeze(0)
935
+ key_states = key_states.transpose(0, 1).unsqueeze(0)
936
+ value_states = value_states.transpose(0, 1).unsqueeze(0)
937
+
938
+ attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
939
+ self.config._attn_implementation, eager_attention_forward
940
+ )
941
+
942
+ if is_flash_attention_requested(self.config):
943
+ # Flash Attention: Use cu_seqlens for variable length attention
944
+ max_seqlen = (cu_seqlens[1:] - cu_seqlens[:-1]).max()
945
+ attn_output, _ = attention_interface(
946
+ self,
947
+ query_states,
948
+ key_states,
949
+ value_states,
950
+ attention_mask=None,
951
+ scaling=self.scaling,
952
+ dropout=0.0 if not self.training else self.attention_dropout,
953
+ cu_seq_lens_q=cu_seqlens,
954
+ cu_seq_lens_k=cu_seqlens,
955
+ max_length_q=max_seqlen,
956
+ max_length_k=max_seqlen,
957
+ is_causal=False,
958
+ **kwargs,
959
+ )
960
+ else:
961
+ # Other implementations: Process each chunk separately
962
+ lengths = cu_seqlens[1:] - cu_seqlens[:-1]
963
+ splits = [
964
+ torch.split(tensor, lengths.tolist(), dim=2) for tensor in (query_states, key_states, value_states)
965
+ ]
966
+
967
+ attn_outputs = [
968
+ attention_interface(
969
+ self,
970
+ q,
971
+ k,
972
+ v,
973
+ attention_mask=None,
974
+ scaling=self.scaling,
975
+ dropout=0.0 if not self.training else self.attention_dropout,
976
+ is_causal=False,
977
+ **kwargs,
978
+ )[0]
979
+ for q, k, v in zip(*splits)
980
+ ]
981
+ attn_output = torch.cat(attn_outputs, dim=1)
982
+
983
+ attn_output = attn_output.reshape(seq_length, -1).contiguous()
984
+ attn_output = self.proj(attn_output)
985
+ return attn_output
986
+
987
+
988
+ class Qwen3_5VisionBlock(GradientCheckpointingLayer):
989
+ def __init__(self, config, attn_implementation: str = "sdpa") -> None:
990
+ super().__init__()
991
+ self.norm1 = nn.LayerNorm(config.hidden_size, eps=1e-6)
992
+ self.norm2 = nn.LayerNorm(config.hidden_size, eps=1e-6)
993
+ self.attn = Qwen3_5VisionAttention(config=config)
994
+ self.mlp = Qwen3_5VisionMLP(config=config)
995
+
996
+ @auto_docstring
997
+ def forward(
998
+ self,
999
+ hidden_states: torch.Tensor,
1000
+ cu_seqlens: torch.Tensor,
1001
+ rotary_pos_emb: torch.Tensor | None = None,
1002
+ position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
1003
+ **kwargs,
1004
+ ) -> torch.Tensor:
1005
+ r"""
1006
+ cu_seqlens (`torch.Tensor`):
1007
+ Cumulative sequence lengths used for packed variable-length attention in Flash Attention kernels.
1008
+ rotary_pos_emb (`torch.Tensor`, *optional*):
1009
+ Precomputed rotary positional embeddings applied to the vision attention query/key states.
1010
+ """
1011
+ hidden_states = hidden_states + self.attn(
1012
+ self.norm1(hidden_states),
1013
+ cu_seqlens=cu_seqlens,
1014
+ rotary_pos_emb=rotary_pos_emb,
1015
+ position_embeddings=position_embeddings,
1016
+ **kwargs,
1017
+ )
1018
+ hidden_states = hidden_states + self.mlp(self.norm2(hidden_states))
1019
+ return hidden_states
1020
+
1021
+
1022
+ class Qwen3_5VisionModel(Qwen3_5PreTrainedModel):
1023
+ config: Qwen3_5VisionConfig
1024
+ input_modalities = ("image", "video")
1025
+ _no_split_modules = ["Qwen3_5VisionBlock"]
1026
+ _can_record_outputs = {
1027
+ "hidden_states": Qwen3_5VisionBlock,
1028
+ "attentions": Qwen3_5VisionAttention,
1029
+ }
1030
+
1031
+ def __init__(self, config, *inputs, **kwargs) -> None:
1032
+ super().__init__(config, *inputs, **kwargs)
1033
+ self.spatial_merge_size = config.spatial_merge_size
1034
+ self.patch_size = config.patch_size
1035
+ self.spatial_merge_unit = self.spatial_merge_size * self.spatial_merge_size
1036
+
1037
+ self.patch_embed = Qwen3_5VisionPatchEmbed(
1038
+ config=config,
1039
+ )
1040
+
1041
+ self.pos_embed = nn.Embedding(config.num_position_embeddings, config.hidden_size)
1042
+ self.num_grid_per_side = int(config.num_position_embeddings**0.5)
1043
+
1044
+ head_dim = config.hidden_size // config.num_heads
1045
+ self.rotary_pos_emb = Qwen3_5VisionRotaryEmbedding(head_dim // 2)
1046
+
1047
+ self.blocks = nn.ModuleList([Qwen3_5VisionBlock(config) for _ in range(config.depth)])
1048
+ self.merger = Qwen3_5VisionPatchMerger(
1049
+ config=config,
1050
+ use_postshuffle_norm=False,
1051
+ )
1052
+
1053
+ self.gradient_checkpointing = False
1054
+
1055
+ self.post_init()
1056
+
1057
+ def rot_pos_emb(self, grid_thw: torch.Tensor) -> torch.Tensor:
1058
+ warnings.warn(
1059
+ f"`{self.__class__.__name__}.rot_pos_emb` is deprecated and will be removed in v5.11. Use `get_vision_position_ids` from `transformers.vision_utils` and apply the rotary embedding module.",
1060
+ FutureWarning,
1061
+ stacklevel=2,
1062
+ )
1063
+ position_ids = get_vision_position_ids(grid_thw, self.spatial_merge_size)
1064
+ rotary_pos_emb = self.rotary_pos_emb(position_ids)
1065
+ return rotary_pos_emb
1066
+
1067
+ def fast_pos_embed_interpolate(self, grid_thw):
1068
+ warnings.warn(
1069
+ f"`{self.__class__.__name__}.fast_pos_embed_interpolate` is deprecated and will be removed in v5.11. Use `get_vision_bilinear_indices_and_weights` from `transformers.vision_utils` and apply `self.pos_embed`.",
1070
+ FutureWarning,
1071
+ stacklevel=2,
1072
+ )
1073
+ bilinear_indices, bilinear_weights = get_vision_bilinear_indices_and_weights(
1074
+ grid_thw,
1075
+ num_grid_per_side=self.num_grid_per_side,
1076
+ spatial_merge_size=self.config.spatial_merge_size,
1077
+ )
1078
+ return (self.pos_embed(bilinear_indices) * bilinear_weights[:, :, None]).sum(0)
1079
+
1080
+ @merge_with_config_defaults
1081
+ @capture_outputs
1082
+ def forward(self, hidden_states: torch.Tensor, grid_thw: torch.Tensor, **kwargs) -> torch.Tensor:
1083
+ """
1084
+ Args:
1085
+ hidden_states (`torch.Tensor` of shape `(seq_len, hidden_size)`):
1086
+ The final hidden states of the model.
1087
+ grid_thw (`torch.Tensor` of shape `(num_images_or_videos, 3)`):
1088
+ The temporal, height and width of feature shape of each image in LLM.
1089
+
1090
+ Returns:
1091
+ `torch.Tensor`: hidden_states.
1092
+ """
1093
+ bilinear_indices, bilinear_weights = get_vision_bilinear_indices_and_weights(
1094
+ grid_thw,
1095
+ num_grid_per_side=self.num_grid_per_side,
1096
+ spatial_merge_size=self.config.spatial_merge_size,
1097
+ kwargs=kwargs,
1098
+ )
1099
+ position_ids = get_vision_position_ids(grid_thw, self.spatial_merge_size, kwargs=kwargs)
1100
+ cu_seqlens = get_vision_cu_seqlens(grid_thw, kwargs=kwargs)
1101
+
1102
+ hidden_states = self.patch_embed(hidden_states)
1103
+ pos_embeds = (self.pos_embed(bilinear_indices) * bilinear_weights[:, :, None]).sum(0)
1104
+ hidden_states = hidden_states + pos_embeds.to(hidden_states.dtype)
1105
+ rotary_pos_emb = self.rotary_pos_emb(position_ids)
1106
+
1107
+ seq_len, _ = hidden_states.size()
1108
+ hidden_states = hidden_states.reshape(seq_len, -1)
1109
+ rotary_pos_emb = rotary_pos_emb.reshape(seq_len, -1)
1110
+ emb = torch.cat((rotary_pos_emb, rotary_pos_emb), dim=-1)
1111
+ position_embeddings = (emb.cos(), emb.sin())
1112
+
1113
+ for blk in self.blocks:
1114
+ hidden_states = blk(
1115
+ hidden_states,
1116
+ cu_seqlens=cu_seqlens,
1117
+ position_embeddings=position_embeddings,
1118
+ **kwargs,
1119
+ )
1120
+
1121
+ merged_hidden_states = self.merger(hidden_states)
1122
+
1123
+ return BaseModelOutputWithPooling(
1124
+ last_hidden_state=hidden_states,
1125
+ pooler_output=merged_hidden_states,
1126
+ )
1127
+
1128
+
1129
+ @auto_docstring(
1130
+ custom_intro="""
1131
+ Base class for Llava outputs, with hidden states and attentions.
1132
+ """
1133
+ )
1134
+ @dataclass
1135
+ class Qwen3_5ModelOutputWithPast(ModelOutput):
1136
+ r"""
1137
+ past_key_values (`Cache`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
1138
+ It is a [`~cache_utils.Cache`] instance. For more details, see our [kv cache guide](https://huggingface.co/docs/transformers/en/kv_cache).
1139
+
1140
+ Contains pre-computed hidden-states (key and values in the self-attention blocks) that can be used (see
1141
+ `past_key_values` input) to speed up sequential decoding.
1142
+ rope_deltas (`torch.LongTensor` of shape `(batch_size, )`, *optional*):
1143
+ The rope index difference between sequence length and multimodal rope.
1144
+ """
1145
+
1146
+ last_hidden_state: torch.FloatTensor | None = None
1147
+ past_key_values: Cache | None = None
1148
+ hidden_states: tuple[torch.FloatTensor] | None = None
1149
+ attentions: tuple[torch.FloatTensor] | None = None
1150
+ rope_deltas: torch.LongTensor | None = None
1151
+
1152
+
1153
+ class Qwen3_5TextModel(Qwen3_5PreTrainedModel):
1154
+ config: Qwen3_5TextConfig
1155
+
1156
+ def __init__(self, config: Qwen3_5TextConfig):
1157
+ super().__init__(config)
1158
+ self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, config.pad_token_id)
1159
+ self.layers = nn.ModuleList(
1160
+ [Qwen3_5DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
1161
+ )
1162
+ self.norm = Qwen3_5RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
1163
+ self.rotary_emb = Qwen3_5TextRotaryEmbedding(config=config)
1164
+ self.gradient_checkpointing = False
1165
+ # Initialize weights and apply final processing
1166
+ self.post_init()
1167
+
1168
+ @merge_with_config_defaults
1169
+ @capture_outputs
1170
+ @auto_docstring
1171
+ def forward(
1172
+ self,
1173
+ input_ids: torch.LongTensor | None = None,
1174
+ attention_mask: torch.Tensor | None = None,
1175
+ position_ids: torch.LongTensor | None = None,
1176
+ past_key_values: Cache | None = None,
1177
+ inputs_embeds: torch.FloatTensor | None = None,
1178
+ use_cache: bool | None = None,
1179
+ **kwargs: Unpack[TransformersKwargs],
1180
+ ) -> BaseModelOutputWithPast:
1181
+ if (input_ids is None) ^ (inputs_embeds is not None):
1182
+ raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
1183
+
1184
+ if inputs_embeds is None:
1185
+ inputs_embeds = self.embed_tokens(input_ids)
1186
+
1187
+ if use_cache and past_key_values is None:
1188
+ past_key_values = DynamicCache(config=self.config)
1189
+
1190
+ # the hard coded `4` is for text, temporal, height and width.
1191
+ if position_ids is None:
1192
+ past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
1193
+ position_ids = torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens
1194
+ position_ids = position_ids.view(1, 1, -1).expand(4, inputs_embeds.shape[0], -1)
1195
+ elif position_ids.ndim == 2:
1196
+ position_ids = position_ids[None, ...].expand(4, position_ids.shape[0], -1)
1197
+
1198
+ if position_ids.ndim == 3 and position_ids.shape[0] == 4:
1199
+ text_position_ids = position_ids[0]
1200
+ position_ids = position_ids[1:]
1201
+ else:
1202
+ text_position_ids = None
1203
+
1204
+ causal_mask = create_causal_mask(
1205
+ config=self.config,
1206
+ inputs_embeds=inputs_embeds,
1207
+ attention_mask=attention_mask,
1208
+ past_key_values=past_key_values,
1209
+ position_ids=text_position_ids,
1210
+ )
1211
+ linear_attn_mask = self._update_linear_attn_mask(attention_mask, past_key_values)
1212
+
1213
+ hidden_states = inputs_embeds
1214
+ position_embeddings = self.rotary_emb(hidden_states, position_ids)
1215
+
1216
+ for i, decoder_layer in enumerate(self.layers[: self.config.num_hidden_layers]):
1217
+ layer_mask = linear_attn_mask if self.config.layer_types[i] == "linear_attention" else causal_mask
1218
+
1219
+ hidden_states = decoder_layer(
1220
+ hidden_states,
1221
+ position_embeddings=position_embeddings,
1222
+ attention_mask=layer_mask,
1223
+ position_ids=text_position_ids,
1224
+ past_key_values=past_key_values,
1225
+ use_cache=use_cache,
1226
+ **kwargs,
1227
+ )
1228
+
1229
+ hidden_states = self.norm(hidden_states)
1230
+
1231
+ return Qwen3_5ModelOutputWithPast(
1232
+ last_hidden_state=hidden_states,
1233
+ past_key_values=past_key_values,
1234
+ )
1235
+
1236
+ def _update_linear_attn_mask(self, attention_mask, past_key_values):
1237
+ """
1238
+ NOTE: Left-padding is used for linear attention mask.
1239
+ No need for zeroing states when
1240
+ 1. Cached forward
1241
+ 2. Attending to all inputs
1242
+ """
1243
+ linear_attn_mask = attention_mask
1244
+ if (past_key_values is not None and past_key_values.has_previous_state()) or (
1245
+ attention_mask is not None and torch.all(attention_mask == 1)
1246
+ ):
1247
+ linear_attn_mask = None
1248
+ return linear_attn_mask
1249
+
1250
+
1251
+ @auto_docstring
1252
+ class Qwen3_5Model(Qwen3_5PreTrainedModel):
1253
+ base_model_prefix = "model"
1254
+ # Reference: fix gemma3 grad acc #37208
1255
+ accepts_loss_kwargs = False
1256
+ config: Qwen3_5Config
1257
+ _no_split_modules = ["Qwen3_5DecoderLayer", "Qwen3_5VisionBlock"]
1258
+
1259
+ def __init__(self, config):
1260
+ super().__init__(config)
1261
+ self.visual = Qwen3_5VisionModel._from_config(config.vision_config)
1262
+ self.language_model = Qwen3_5TextModel._from_config(config.text_config)
1263
+ self.rope_deltas = None # cache rope_deltas here
1264
+
1265
+ # Initialize weights and apply final processing
1266
+ self.post_init()
1267
+
1268
+ def get_vision_position_ids(
1269
+ self,
1270
+ start_position: int,
1271
+ grid_thw: list[int, int, int] | torch.Tensor,
1272
+ temp_merge_size: int = 1,
1273
+ spatial_merge_size: int = 1,
1274
+ time_interval: int = 1,
1275
+ device: str | torch.device | None = None,
1276
+ ):
1277
+ """
1278
+ Compute 3D positional indices for vision tokens derived from a single image or video input.
1279
+
1280
+ The positions are generated from the input grid defined by temporal (T), height (H), and
1281
+ width (W) dimensions. Temporal and spatial dimensions can be downscaled according to the
1282
+ merge sizes used in the vision backbone. The resulting positions are offset by `start_position`.
1283
+
1284
+ Args:
1285
+ start_position (`int`):
1286
+ Offset added to all computed positional indices.
1287
+ grid_thw (`Sequence[int]` or `torch.Tensor` of shape `(3,)`):
1288
+ The (T, H, W) grid representing the feature layout of the current image or video after patch embedding.
1289
+ temp_merge_size (`int`, *optional*):
1290
+ Factor by which the temporal dimension is reduced in the backbone. The temporal grid size is divided
1291
+ by this value. Defaults to 1.
1292
+ spatial_merge_size (`int`, *optional*):
1293
+ Factor by which the spatial dimensions (H and W) are reduced in the backbone. Both H and W are divided
1294
+ by this value. Defaults to 1.
1295
+ time_interval (`int`, *optional*):
1296
+ Spacing factor applied between consecutive temporal position indices.Defaults to 1.
1297
+ device (`str` or `torch.device`, *optional*):
1298
+ Device on which the resulting tensor is allocated. If `None`, uses the current default device.
1299
+
1300
+ Returns:
1301
+ torch.LongTensor of shape (3, sequence_length):
1302
+ Positional indices for temporal, height, and width dimensions,
1303
+ flattened into sequence form and offset by `start_position`.
1304
+ """
1305
+ llm_grid_t, llm_grid_h, llm_grid_w = (
1306
+ grid_thw[0].item() // temp_merge_size,
1307
+ grid_thw[1].item() // spatial_merge_size,
1308
+ grid_thw[2].item() // spatial_merge_size,
1309
+ )
1310
+
1311
+ # Add `start_position` after arange for compile
1312
+ position_temporal = torch.arange(llm_grid_t, device=device) * time_interval
1313
+ position_width = torch.arange(llm_grid_w, device=device) + start_position
1314
+ position_height = torch.arange(llm_grid_h, device=device) + start_position
1315
+
1316
+ # Repeat the positions per each grid and per video frame. Repeat patterns are important
1317
+ # do not modify without checking values!
1318
+ position_width = position_width.repeat(llm_grid_h * llm_grid_t)
1319
+ position_height = position_height.repeat_interleave(llm_grid_w).repeat(llm_grid_t)
1320
+ # Important: add `start_positions` after applying `time_interval`, order matters
1321
+ position_temporal = position_temporal.repeat_interleave(llm_grid_h * llm_grid_w) + start_position
1322
+ vision_position_ids = torch.stack([position_temporal, position_height, position_width], dim=0)
1323
+
1324
+ return vision_position_ids
1325
+
1326
+ def get_rope_index(
1327
+ self,
1328
+ input_ids: torch.LongTensor,
1329
+ mm_token_type_ids: torch.IntTensor,
1330
+ image_grid_thw: torch.LongTensor | None = None,
1331
+ video_grid_thw: torch.LongTensor | None = None,
1332
+ attention_mask: torch.Tensor | None = None,
1333
+ **kwargs,
1334
+ ) -> tuple[torch.Tensor, torch.Tensor]:
1335
+ """
1336
+ Difference from Qwen2VL/Qwen2.5VL's get_rope_index:
1337
+ - Since Qwen3.5 use timestamps to separate videos, like <t1> <vision_start> <frame1> <vision_end> <t2> <vision_start> <frame2> <vision_end>, the video_grid_thw should also be split too.
1338
+
1339
+ Args:
1340
+ input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
1341
+ Indices of input sequence tokens in the vocabulary. Padding will be ignored by default should you provide
1342
+ it.
1343
+ mm_token_type_ids (`torch.IntTensor` of shape `(batch_size, sequence_length)`):
1344
+ Token type ids matching each modality to a different value in the input sequence, i.e. text (0), image (1), video (2).
1345
+ image_grid_thw (`torch.LongTensor` of shape `(num_images, 3)`, *optional*):
1346
+ The temporal, height and width of feature shape of each image in LLM.
1347
+ video_grid_thw (`torch.LongTensor` of shape `(num_videos, 3)`, *optional*):
1348
+ The temporal, height and width of feature shape of each video in LLM.
1349
+ attention_mask (`torch.Tensor` of shape `(batch_size, sequence_length)`, *optional*):
1350
+ Mask to avoid performing attention on padding token indices. Mask values selected in `[0, 1]`:
1351
+
1352
+ - 1 for tokens that are **not masked**,
1353
+ - 0 for tokens that are **masked**.
1354
+
1355
+ Returns:
1356
+ position_ids (`torch.LongTensor` of shape `(3, batch_size, sequence_length)`)
1357
+ mrope_position_deltas (`torch.Tensor` of shape `(batch_size)`)
1358
+ """
1359
+
1360
+ # Separate video grid thw into multiple grids because timestamps are used to separate videos.
1361
+ if video_grid_thw is not None:
1362
+ video_grid_thw = torch.repeat_interleave(video_grid_thw, video_grid_thw[:, 0], dim=0)
1363
+ video_grid_thw[:, 0] = 1
1364
+ spatial_merge_size = self.config.vision_config.spatial_merge_size
1365
+
1366
+ mrope_position_deltas = []
1367
+ position_ids = torch.zeros(
1368
+ 3,
1369
+ input_ids.shape[0],
1370
+ input_ids.shape[1],
1371
+ dtype=input_ids.dtype,
1372
+ device=input_ids.device,
1373
+ )
1374
+ grid_iters = {
1375
+ 1: iter(image_grid_thw) if image_grid_thw is not None else None,
1376
+ 2: iter(video_grid_thw) if video_grid_thw is not None else None,
1377
+ }
1378
+
1379
+ for batch_idx, current_input_ids in enumerate(input_ids):
1380
+ input_token_type = mm_token_type_ids[batch_idx]
1381
+ if attention_mask is not None:
1382
+ current_input_ids = current_input_ids[attention_mask[batch_idx].bool()]
1383
+ input_token_type = input_token_type[attention_mask[batch_idx].bool()]
1384
+
1385
+ input_type_group = []
1386
+ for key, group in itertools.groupby(enumerate(input_token_type.tolist()), lambda x: x[1]):
1387
+ group = list(group)
1388
+ start_index = group[0][0]
1389
+ end_index = group[-1][0] + 1
1390
+ input_type_group.append((key, start_index, end_index))
1391
+
1392
+ current_pos = 0
1393
+ llm_pos_ids_list = []
1394
+ for modality_type, start_idx, end_idx in input_type_group:
1395
+ # text == 0
1396
+ if modality_type == 0:
1397
+ text_len = end_idx - start_idx
1398
+ llm_pos_ids_list.append(
1399
+ torch.arange(text_len, device=input_ids.device).view(1, -1).expand(3, -1) + current_pos
1400
+ )
1401
+ current_pos += text_len
1402
+ # image == 1, video == 2
1403
+ else:
1404
+ grid_thw = next(grid_iters[modality_type])
1405
+ vision_position_ids = self.get_vision_position_ids(
1406
+ current_pos, grid_thw, 1, spatial_merge_size, device=input_ids.device
1407
+ )
1408
+ llm_pos_ids_list.append(vision_position_ids)
1409
+ current_pos += max(grid_thw[1], grid_thw[2]) // spatial_merge_size
1410
+ llm_positions = torch.cat(llm_pos_ids_list, dim=1).reshape(3, -1)
1411
+ if attention_mask is not None:
1412
+ position_ids[:, batch_idx, attention_mask[batch_idx].bool()] = llm_positions.to(position_ids.device)
1413
+ else:
1414
+ position_ids[:, batch_idx] = llm_positions.to(position_ids.device)
1415
+ mrope_position_deltas.append(llm_positions.max() + 1 - len(current_input_ids))
1416
+ mrope_position_deltas = torch.tensor(mrope_position_deltas, device=input_ids.device).unsqueeze(1)
1417
+ return position_ids, mrope_position_deltas
1418
+
1419
+ @accepts_precomputed_kwargs(modality="video")
1420
+ @can_return_tuple
1421
+ @auto_docstring
1422
+ def get_video_features(
1423
+ self,
1424
+ pixel_values_videos: torch.FloatTensor,
1425
+ video_grid_thw: torch.LongTensor | None = None,
1426
+ **kwargs: Unpack[TransformersKwargs],
1427
+ ) -> tuple | BaseModelOutputWithPooling:
1428
+ r"""
1429
+ pixel_values_videos (`torch.FloatTensor` of shape `(batch_size, num_channels, image_size, image_size)`):
1430
+ The tensors corresponding to the input videos.
1431
+ video_grid_thw (`torch.LongTensor` of shape `(num_videos, 3)`, *optional*):
1432
+ The temporal, height and width of feature shape of each video in LLM.
1433
+ """
1434
+ # Same implementation as for images
1435
+ return self.get_image_features(pixel_values_videos, video_grid_thw, **kwargs)
1436
+
1437
+ @accepts_precomputed_kwargs(modality="image")
1438
+ @can_return_tuple
1439
+ @auto_docstring
1440
+ def get_image_features(
1441
+ self,
1442
+ pixel_values: torch.FloatTensor,
1443
+ image_grid_thw: torch.LongTensor | None = None,
1444
+ **kwargs: Unpack[TransformersKwargs],
1445
+ ) -> tuple | BaseModelOutputWithPooling:
1446
+ r"""
1447
+ pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, image_size, image_size)`):
1448
+ The tensors corresponding to the input images.
1449
+ image_grid_thw (`torch.LongTensor` of shape `(num_images, 3)`, *optional*):
1450
+ The temporal, height and width of feature shape of each image in LLM.
1451
+ """
1452
+ pixel_values = pixel_values.type(self.visual.dtype)
1453
+ vision_output: BaseModelOutputWithPooling = self.visual(
1454
+ pixel_values, grid_thw=image_grid_thw, return_dict=True, **kwargs
1455
+ )
1456
+ image_embeds = vision_output.pooler_output
1457
+ split_sizes = (image_grid_thw.prod(-1) // self.visual.spatial_merge_size**2).tolist()
1458
+ image_embeds = torch.split(image_embeds, split_sizes)
1459
+ vision_output.pooler_output = image_embeds
1460
+
1461
+ return vision_output
1462
+
1463
+ def get_placeholder_mask(
1464
+ self,
1465
+ input_ids: torch.LongTensor,
1466
+ inputs_embeds: torch.FloatTensor,
1467
+ image_features: torch.FloatTensor | None = None,
1468
+ video_features: torch.FloatTensor | None = None,
1469
+ ):
1470
+ """
1471
+ Obtains multimodal placeholder mask from `input_ids` or `inputs_embeds`, and checks that the placeholder token count is
1472
+ equal to the length of multimodal features. If the lengths are different, an error is raised.
1473
+ """
1474
+ if input_ids is None:
1475
+ special_image_mask = inputs_embeds == self.get_input_embeddings()(
1476
+ torch.tensor(self.config.image_token_id, dtype=torch.long, device=inputs_embeds.device)
1477
+ )
1478
+ special_image_mask = special_image_mask.all(-1)
1479
+ special_video_mask = inputs_embeds == self.get_input_embeddings()(
1480
+ torch.tensor(self.config.video_token_id, dtype=torch.long, device=inputs_embeds.device)
1481
+ )
1482
+ special_video_mask = special_video_mask.all(-1)
1483
+ else:
1484
+ special_image_mask = input_ids == self.config.image_token_id
1485
+ special_video_mask = input_ids == self.config.video_token_id
1486
+
1487
+ n_image_tokens = special_image_mask.sum()
1488
+ special_image_mask = special_image_mask.unsqueeze(-1).expand_as(inputs_embeds).to(inputs_embeds.device)
1489
+ if image_features is not None:
1490
+ torch_compilable_check(
1491
+ inputs_embeds[special_image_mask].numel() == image_features.numel(),
1492
+ f"Image features and image tokens do not match, tokens: {n_image_tokens}, features: {image_features.shape[0]}",
1493
+ )
1494
+
1495
+ n_video_tokens = special_video_mask.sum()
1496
+ special_video_mask = special_video_mask.unsqueeze(-1).expand_as(inputs_embeds).to(inputs_embeds.device)
1497
+ if video_features is not None:
1498
+ torch_compilable_check(
1499
+ inputs_embeds[special_video_mask].numel() == video_features.numel(),
1500
+ f"Video features and video tokens do not match, tokens: {n_video_tokens}, features: {video_features.shape[0]}",
1501
+ )
1502
+ return special_image_mask, special_video_mask
1503
+
1504
+ def compute_3d_position_ids(
1505
+ self,
1506
+ input_ids: torch.Tensor | None,
1507
+ inputs_embeds: torch.Tensor | None,
1508
+ image_grid_thw: torch.Tensor | None = None,
1509
+ video_grid_thw: torch.Tensor | None = None,
1510
+ attention_mask: torch.Tensor | None = None,
1511
+ past_key_values: torch.Tensor | None = None,
1512
+ mm_token_type_ids: torch.IntTensor | None = None,
1513
+ ) -> torch.Tensor | None:
1514
+ past_key_values_length = 0 if past_key_values is None else past_key_values.get_seq_length()
1515
+ has_multimodal = image_grid_thw is not None or video_grid_thw is not None
1516
+ if has_multimodal and mm_token_type_ids is None and input_ids is not None:
1517
+ raise ValueError(
1518
+ "Multimodal data was passed (via `image_grid_thw` or `video_grid_thw`) but `mm_token_type_ids` is "
1519
+ "missing. Please pass `mm_token_type_ids` to the model so that multimodal RoPE (M-RoPE) can be "
1520
+ "computed correctly. `mm_token_type_ids` is returned by the processor alongside `input_ids`."
1521
+ )
1522
+ can_compute_mrope = input_ids is not None and mm_token_type_ids is not None and has_multimodal
1523
+
1524
+ if can_compute_mrope and (self.rope_deltas is None or past_key_values_length == 0):
1525
+ position_ids, rope_deltas = self.get_rope_index(
1526
+ input_ids,
1527
+ image_grid_thw=image_grid_thw,
1528
+ video_grid_thw=video_grid_thw,
1529
+ attention_mask=attention_mask,
1530
+ mm_token_type_ids=mm_token_type_ids,
1531
+ )
1532
+ self.rope_deltas = rope_deltas
1533
+ # Use pre-calculated rope-deltas to infer correct 3D position ids during incremental
1534
+ # generation (past_key_values_length > 0) or when only inputs_embeds is provided (no input_ids
1535
+ # to recompute from). Skip when input_ids is provided without past_key_values to avoid shape
1536
+ # mismatches from stale rope_deltas (e.g., training forward pass after generation).
1537
+ elif self.rope_deltas is not None and (past_key_values_length > 0 or input_ids is None):
1538
+ batch_size, seq_length, _ = inputs_embeds.shape
1539
+ if attention_mask is not None:
1540
+ position_ids = attention_mask.long().cumsum(-1) - 1
1541
+ position_ids = position_ids.masked_fill(attention_mask == 0, 0)
1542
+ position_ids = position_ids.view(1, batch_size, -1).repeat(3, 1, 1).to(inputs_embeds.device)
1543
+ else:
1544
+ position_ids = torch.arange(past_key_values_length, past_key_values_length + seq_length)
1545
+ position_ids = position_ids.view(1, 1, -1).expand(3, batch_size, -1).to(inputs_embeds.device)
1546
+ delta = self.rope_deltas.repeat_interleave(batch_size // self.rope_deltas.shape[0], dim=0)
1547
+ position_ids = position_ids + delta.to(device=inputs_embeds.device)
1548
+ else:
1549
+ # Can't build correct 3D positions. Let the model infer it
1550
+ position_ids = None
1551
+ return position_ids
1552
+
1553
+ @auto_docstring
1554
+ @can_return_tuple
1555
+ def forward(
1556
+ self,
1557
+ input_ids: torch.LongTensor = None,
1558
+ attention_mask: torch.Tensor | None = None,
1559
+ position_ids: torch.LongTensor | None = None,
1560
+ past_key_values: Cache | None = None,
1561
+ inputs_embeds: torch.FloatTensor | None = None,
1562
+ pixel_values: torch.Tensor | None = None,
1563
+ pixel_values_videos: torch.FloatTensor | None = None,
1564
+ image_grid_thw: torch.LongTensor | None = None,
1565
+ video_grid_thw: torch.LongTensor | None = None,
1566
+ mm_token_type_ids: torch.IntTensor | None = None,
1567
+ **kwargs: Unpack[TransformersKwargs],
1568
+ ) -> tuple | Qwen3_5ModelOutputWithPast:
1569
+ r"""
1570
+ image_grid_thw (`torch.LongTensor` of shape `(num_images, 3)`, *optional*):
1571
+ The temporal, height and width of feature shape of each image in LLM.
1572
+ video_grid_thw (`torch.LongTensor` of shape `(num_videos, 3)`, *optional*):
1573
+ The temporal, height and width of feature shape of each video in LLM.
1574
+ """
1575
+ if (input_ids is None) ^ (inputs_embeds is not None):
1576
+ raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
1577
+
1578
+ if inputs_embeds is None:
1579
+ inputs_embeds = self.get_input_embeddings()(input_ids)
1580
+
1581
+ if pixel_values is not None:
1582
+ image_outputs: BaseModelOutputWithPooling = self.get_image_features(
1583
+ pixel_values, image_grid_thw, return_dict=True, **kwargs
1584
+ )
1585
+ image_embeds = image_outputs.pooler_output
1586
+ image_embeds = torch.cat(image_embeds, dim=0).to(inputs_embeds.device, inputs_embeds.dtype)
1587
+ image_mask, _ = self.get_placeholder_mask(
1588
+ input_ids, inputs_embeds=inputs_embeds, image_features=image_embeds
1589
+ )
1590
+ inputs_embeds = inputs_embeds.masked_scatter(image_mask, image_embeds)
1591
+
1592
+ if pixel_values_videos is not None:
1593
+ video_outputs: BaseModelOutputWithPooling = self.get_video_features(
1594
+ pixel_values_videos, video_grid_thw, return_dict=True, **kwargs
1595
+ )
1596
+ video_embeds = video_outputs.pooler_output
1597
+ video_embeds = torch.cat(video_embeds, dim=0).to(inputs_embeds.device, inputs_embeds.dtype)
1598
+ _, video_mask = self.get_placeholder_mask(
1599
+ input_ids, inputs_embeds=inputs_embeds, video_features=video_embeds
1600
+ )
1601
+ inputs_embeds = inputs_embeds.masked_scatter(video_mask, video_embeds)
1602
+
1603
+ if position_ids is None:
1604
+ position_ids = self.compute_3d_position_ids(
1605
+ input_ids=input_ids,
1606
+ image_grid_thw=image_grid_thw,
1607
+ video_grid_thw=video_grid_thw,
1608
+ inputs_embeds=inputs_embeds,
1609
+ attention_mask=attention_mask,
1610
+ past_key_values=past_key_values,
1611
+ mm_token_type_ids=mm_token_type_ids,
1612
+ )
1613
+
1614
+ outputs = self.language_model(
1615
+ input_ids=None,
1616
+ position_ids=position_ids,
1617
+ attention_mask=attention_mask,
1618
+ past_key_values=past_key_values,
1619
+ inputs_embeds=inputs_embeds,
1620
+ **kwargs,
1621
+ )
1622
+
1623
+ return Qwen3_5ModelOutputWithPast(
1624
+ **outputs,
1625
+ rope_deltas=self.rope_deltas,
1626
+ )
1627
+
1628
+
1629
+ @auto_docstring
1630
+ class Qwen3_5ForCausalLM(Qwen3_5PreTrainedModel, GenerationMixin):
1631
+ _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
1632
+ _tp_plan = {"lm_head": "colwise_gather_output"}
1633
+ _pp_plan = {"lm_head": (["hidden_states"], ["logits"])}
1634
+ config: Qwen3_5TextConfig
1635
+ _keys_to_ignore_on_load_unexpected = [r"^mtp.*", r"^model.visual.*"]
1636
+
1637
+ def __init__(self, config):
1638
+ super().__init__(config)
1639
+ self.model = Qwen3_5TextModel(config)
1640
+ self.vocab_size = config.vocab_size
1641
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
1642
+
1643
+ # Initialize weights and apply final processing
1644
+ self.post_init()
1645
+
1646
+ @can_return_tuple
1647
+ @auto_docstring
1648
+ def forward(
1649
+ self,
1650
+ input_ids: torch.LongTensor | None = None,
1651
+ attention_mask: torch.Tensor | None = None,
1652
+ position_ids: torch.LongTensor | None = None,
1653
+ past_key_values: Cache | None = None,
1654
+ inputs_embeds: torch.FloatTensor | None = None,
1655
+ labels: torch.LongTensor | None = None,
1656
+ use_cache: bool | None = None,
1657
+ logits_to_keep: int | torch.Tensor = 0,
1658
+ **kwargs: Unpack[TransformersKwargs],
1659
+ ) -> CausalLMOutputWithPast:
1660
+ r"""
1661
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
1662
+ Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
1663
+ config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
1664
+ (masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
1665
+
1666
+ Example:
1667
+
1668
+ ```python
1669
+ >>> from transformers import AutoTokenizer, Qwen3_5ForCausalLM
1670
+
1671
+ >>> model = Qwen3_5ForCausalLM.from_pretrained("Qwen/Qwen3_5-8B")
1672
+ >>> tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3_5-8B")
1673
+
1674
+ >>> prompt = "Hey, are you conscious? Can you talk to me?"
1675
+ >>> inputs = tokenizer(prompt, return_tensors="pt")
1676
+
1677
+ >>> # Generate
1678
+ >>> generate_ids = model.generate(inputs.input_ids, max_length=30)
1679
+ >>> tokenizer.batch_decode(generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
1680
+ "Hey, are you conscious? Can you talk to me?\nI'm not conscious, but I can talk to you."
1681
+ ```"""
1682
+ outputs: BaseModelOutputWithPast = self.model(
1683
+ input_ids=input_ids,
1684
+ attention_mask=attention_mask,
1685
+ position_ids=position_ids,
1686
+ past_key_values=past_key_values,
1687
+ inputs_embeds=inputs_embeds,
1688
+ use_cache=use_cache,
1689
+ **kwargs,
1690
+ )
1691
+
1692
+ hidden_states = outputs.last_hidden_state
1693
+ # Only compute necessary logits, and do not upcast them to float if we are not computing the loss
1694
+ slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
1695
+ logits = self.lm_head(hidden_states[:, slice_indices, :])
1696
+
1697
+ loss = None
1698
+ if labels is not None:
1699
+ loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size, **kwargs)
1700
+
1701
+ return CausalLMOutputWithPast(
1702
+ loss=loss,
1703
+ logits=logits,
1704
+ past_key_values=outputs.past_key_values,
1705
+ hidden_states=outputs.hidden_states,
1706
+ attentions=outputs.attentions,
1707
+ )
1708
+
1709
+
1710
+ class Qwen3_5ForTokenClassification(GenericForTokenClassification, Qwen3_5PreTrainedModel):
1711
+ config: Qwen3_5Config
1712
+
1713
+
1714
+ @auto_docstring(
1715
+ custom_intro="""
1716
+ Base class for Qwen3_5 causal language model (or autoregressive) outputs.
1717
+ """
1718
+ )
1719
+ @dataclass
1720
+ class Qwen3_5CausalLMOutputWithPast(ModelOutput):
1721
+ r"""
1722
+ loss (`torch.FloatTensor` of shape `(1,)`, *optional*, returned when `labels` is provided):
1723
+ Language modeling loss (for next-token prediction).
1724
+ logits (`torch.FloatTensor` of shape `(batch_size, sequence_length, config.vocab_size)`):
1725
+ Prediction scores of the language modeling head (scores for each vocabulary token before SoftMax).
1726
+ past_key_values (`Cache`, *optional*, returned when `use_cache=True` is passed or when `config.use_cache=True`):
1727
+ It is a [`~cache_utils.Cache`] instance. For more details, see our [kv cache guide](https://huggingface.co/docs/transformers/en/kv_cache).
1728
+
1729
+ Contains pre-computed hidden-states (key and values in the self-attention blocks) that can be used (see
1730
+ `past_key_values` input) to speed up sequential decoding.
1731
+ rope_deltas (`torch.LongTensor` of shape `(batch_size, )`, *optional*):
1732
+ The rope index difference between sequence length and multimodal rope.
1733
+ """
1734
+
1735
+ loss: torch.FloatTensor | None = None
1736
+ logits: torch.FloatTensor | None = None
1737
+ past_key_values: Cache | None = None
1738
+ hidden_states: tuple[torch.FloatTensor] | None = None
1739
+ attentions: tuple[torch.FloatTensor] | None = None
1740
+ rope_deltas: torch.LongTensor | None = None
1741
+
1742
+
1743
+ class Qwen3_5ForConditionalGeneration(Qwen3_5PreTrainedModel, GenerationMixin):
1744
+ _tied_weights_keys = {"lm_head.weight": "model.language_model.embed_tokens.weight"}
1745
+ # Reference: fix gemma3 grad acc #37208
1746
+ accepts_loss_kwargs = False
1747
+ config: Qwen3_5Config
1748
+
1749
+ def __init__(self, config):
1750
+ super().__init__(config)
1751
+ self.model = Qwen3_5Model(config)
1752
+ self.lm_head = nn.Linear(config.text_config.hidden_size, config.text_config.vocab_size, bias=False)
1753
+
1754
+ self.post_init()
1755
+
1756
+ @auto_docstring
1757
+ def get_video_features(
1758
+ self,
1759
+ pixel_values_videos: torch.FloatTensor,
1760
+ video_grid_thw: torch.LongTensor | None = None,
1761
+ **kwargs: Unpack[TransformersKwargs],
1762
+ ) -> tuple | BaseModelOutputWithPooling:
1763
+ r"""
1764
+ pixel_values_videos (`torch.FloatTensor` of shape `(batch_size, num_channels, image_size, image_size)`):
1765
+ The tensors corresponding to the input videos.
1766
+ video_grid_thw (`torch.LongTensor` of shape `(num_videos, 3)`, *optional*):
1767
+ The temporal, height and width of feature shape of each video in LLM.
1768
+ """
1769
+ return self.model.get_video_features(pixel_values_videos, video_grid_thw, **kwargs)
1770
+
1771
+ @auto_docstring
1772
+ def get_image_features(
1773
+ self,
1774
+ pixel_values: torch.FloatTensor,
1775
+ image_grid_thw: torch.LongTensor | None = None,
1776
+ **kwargs: Unpack[TransformersKwargs],
1777
+ ) -> tuple | BaseModelOutputWithPooling:
1778
+ r"""
1779
+ pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, image_size, image_size)`):
1780
+ The tensors corresponding to the input images.
1781
+ image_grid_thw (`torch.LongTensor` of shape `(num_images, 3)`, *optional*):
1782
+ The temporal, height and width of feature shape of each image in LLM.
1783
+ """
1784
+ return self.model.get_image_features(pixel_values, image_grid_thw, **kwargs)
1785
+
1786
+ @can_return_tuple
1787
+ def forward(
1788
+ self,
1789
+ input_ids: torch.LongTensor = None,
1790
+ attention_mask: torch.Tensor | None = None,
1791
+ position_ids: torch.LongTensor | None = None,
1792
+ past_key_values: Cache | None = None,
1793
+ inputs_embeds: torch.FloatTensor | None = None,
1794
+ labels: torch.LongTensor | None = None,
1795
+ pixel_values: torch.Tensor | None = None,
1796
+ pixel_values_videos: torch.FloatTensor | None = None,
1797
+ image_grid_thw: torch.LongTensor | None = None,
1798
+ video_grid_thw: torch.LongTensor | None = None,
1799
+ mm_token_type_ids: torch.IntTensor | None = None,
1800
+ logits_to_keep: int | torch.Tensor = 0,
1801
+ **kwargs: Unpack[TransformersKwargs],
1802
+ ) -> tuple | Qwen3_5CausalLMOutputWithPast:
1803
+ r"""
1804
+ labels (`torch.LongTensor` of shape `(batch_size, sequence_length)`, *optional*):
1805
+ Labels for computing the masked language modeling loss. Indices should either be in `[0, ...,
1806
+ config.vocab_size]` or -100 (see `input_ids` docstring). Tokens with indices set to `-100` are ignored
1807
+ (masked), the loss is only computed for the tokens with labels in `[0, ..., config.vocab_size]`.
1808
+ image_grid_thw (`torch.LongTensor` of shape `(num_images, 3)`, *optional*):
1809
+ The temporal, height and width of feature shape of each image in LLM.
1810
+ video_grid_thw (`torch.LongTensor` of shape `(num_videos, 3)`, *optional*):
1811
+ The temporal, height and width of feature shape of each video in LLM.
1812
+
1813
+ Example:
1814
+
1815
+ ```python
1816
+ >>> from transformers import AutoProcessor, Qwen3_5ForConditionalGeneration
1817
+
1818
+ >>> model = Qwen3_5ForConditionalGeneration.from_pretrained("Qwen/Qwen3-VL-8B-Instruct")
1819
+ >>> processor = AutoProcessor.from_pretrained("Qwen/Qwen3-VL-8B-Instruct")
1820
+
1821
+ >>> messages = [
1822
+ {
1823
+ "role": "user",
1824
+ "content": [
1825
+ {
1826
+ "type": "image",
1827
+ "image": "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/pipeline-cat-chonk.jpeg",
1828
+ },
1829
+ {"type": "text", "text": "Describe the image."},
1830
+ ],
1831
+ }
1832
+ ]
1833
+
1834
+ >>> inputs = processor.apply_chat_template(
1835
+ messages,
1836
+ tokenize=True,
1837
+ add_generation_prompt=True,
1838
+ return_dict=True,
1839
+ return_tensors="pt"
1840
+ )
1841
+
1842
+ >>> # Generate
1843
+ >>> generated_ids = model.generate(**inputs, max_new_tokens=1024)
1844
+ >>> generated_ids_trimmed = [out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)]
1845
+ >>> output_text = processor.batch_decode(generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False)[0]
1846
+ >>> print(output_text)
1847
+ ```
1848
+ """
1849
+
1850
+ outputs = self.model(
1851
+ input_ids=input_ids,
1852
+ pixel_values=pixel_values,
1853
+ pixel_values_videos=pixel_values_videos,
1854
+ image_grid_thw=image_grid_thw,
1855
+ video_grid_thw=video_grid_thw,
1856
+ position_ids=position_ids,
1857
+ attention_mask=attention_mask,
1858
+ past_key_values=past_key_values,
1859
+ inputs_embeds=inputs_embeds,
1860
+ mm_token_type_ids=mm_token_type_ids,
1861
+ **kwargs,
1862
+ )
1863
+
1864
+ hidden_states = outputs[0]
1865
+
1866
+ # Only compute necessary logits, and do not upcast them to float if we are not computing the loss
1867
+ slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
1868
+ logits = self.lm_head(hidden_states[:, slice_indices, :])
1869
+
1870
+ loss = None
1871
+ if labels is not None:
1872
+ loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.text_config.vocab_size)
1873
+
1874
+ return Qwen3_5CausalLMOutputWithPast(
1875
+ loss=loss,
1876
+ logits=logits,
1877
+ past_key_values=outputs.past_key_values,
1878
+ hidden_states=outputs.hidden_states,
1879
+ attentions=outputs.attentions,
1880
+ rope_deltas=outputs.rope_deltas,
1881
+ )
1882
+
1883
+ def prepare_inputs_for_generation(
1884
+ self,
1885
+ input_ids,
1886
+ past_key_values=None,
1887
+ attention_mask=None,
1888
+ inputs_embeds=None,
1889
+ position_ids=None,
1890
+ use_cache=True,
1891
+ pixel_values=None,
1892
+ pixel_values_videos=None,
1893
+ image_grid_thw=None,
1894
+ video_grid_thw=None,
1895
+ is_first_iteration=False,
1896
+ **kwargs,
1897
+ ):
1898
+ # Overwritten -- in specific circumstances we don't want to forward image inputs to the model
1899
+
1900
+ model_inputs = super().prepare_inputs_for_generation(
1901
+ input_ids,
1902
+ past_key_values=past_key_values,
1903
+ attention_mask=attention_mask,
1904
+ inputs_embeds=inputs_embeds,
1905
+ position_ids=position_ids,
1906
+ pixel_values=pixel_values,
1907
+ pixel_values_videos=pixel_values_videos,
1908
+ image_grid_thw=image_grid_thw,
1909
+ video_grid_thw=video_grid_thw,
1910
+ use_cache=use_cache,
1911
+ is_first_iteration=is_first_iteration,
1912
+ **kwargs,
1913
+ )
1914
+
1915
+ if not is_first_iteration and use_cache:
1916
+ model_inputs["pixel_values"] = None
1917
+ model_inputs["pixel_values_videos"] = None
1918
+
1919
+ return model_inputs
1920
+
1921
+ def _prepare_position_ids_for_generation(self, inputs_tensor, model_kwargs):
1922
+ # Overwritten -- requires 3D position ids
1923
+
1924
+ text_positions = super()._prepare_position_ids_for_generation(inputs_tensor, model_kwargs)
1925
+
1926
+ # Early exit in case we are continuing generation from past kv
1927
+ past_length = 0
1928
+ if (cache := model_kwargs.get("past_key_values")) is not None:
1929
+ past_length = cache.get_seq_length()
1930
+ if past_length != 0 and self.model.rope_deltas is not None:
1931
+ position_ids = text_positions[None, ...] + self.model.rope_deltas
1932
+ return position_ids
1933
+
1934
+ # Otherwise compute 3d position ids for vision tokens and concat with text position ids
1935
+ if "input_ids" in model_kwargs and model_kwargs["input_ids"].shape[1] > 0:
1936
+ inputs_tensor = model_kwargs["input_ids"]
1937
+
1938
+ is_input_ids = len(inputs_tensor.shape) == 2 and inputs_tensor.dtype in [torch.int, torch.long]
1939
+ if (
1940
+ is_input_ids
1941
+ and model_kwargs.get("mm_token_type_ids") is not None
1942
+ and (model_kwargs.get("image_grid_thw") is not None or model_kwargs.get("video_grid_thw") is not None)
1943
+ ):
1944
+ model_kwargs = {k: v for k, v in model_kwargs.items() if k != "input_ids"}
1945
+ vision_positions, rope_deltas = self.model.get_rope_index(inputs_tensor, **model_kwargs)
1946
+ self.model.rope_deltas = rope_deltas
1947
+ else:
1948
+ vision_positions = text_positions.unsqueeze(0).expand(3, -1, -1)
1949
+ self.model.rope_deltas = torch.zeros(
1950
+ inputs_tensor.shape[0], 1, dtype=torch.long, device=inputs_tensor.device
1951
+ )
1952
+
1953
+ # Concatenate "text + vision" positions into [4, bs, seq-len]
1954
+ text_positions = text_positions[None, ...]
1955
+ position_ids = torch.cat([text_positions, vision_positions], dim=0)
1956
+
1957
+ return position_ids
1958
+
1959
+ def _get_image_nums_and_video_nums(
1960
+ self,
1961
+ input_ids: torch.LongTensor | None,
1962
+ inputs_embeds: torch.Tensor | None = None,
1963
+ ) -> tuple[torch.Tensor, torch.Tensor]:
1964
+ """
1965
+ Get the number of images and videos for each sample to calculate the separation length of the sample tensor.
1966
+ These parameters are not passed through the processor to avoid unpredictable impacts from interface modifications.
1967
+
1968
+ Args:
1969
+ input_ids (`torch.LongTensor` of shape `(batch_size, sequence_length)`):
1970
+ Indices of input sequence tokens in the vocabulary.
1971
+
1972
+ Returns:
1973
+ image_nums (`torch.LongTensor` of shape `(batch_size, num_images_sample)`)
1974
+ video_nums (`torch.LongTensor` of shape `(batch_size, num_videos_sample)`)
1975
+ """
1976
+ image_token_id = self.config.image_token_id
1977
+ video_token_id = self.config.video_token_id
1978
+ vision_start_token_id = self.config.vision_start_token_id
1979
+
1980
+ if inputs_embeds is not None:
1981
+ vision_start_mask = (
1982
+ inputs_embeds
1983
+ == self.get_input_embeddings()(
1984
+ torch.tensor(vision_start_token_id, dtype=torch.long, device=inputs_embeds.device)
1985
+ )
1986
+ )[..., 0]
1987
+ image_mask = (
1988
+ inputs_embeds
1989
+ == self.get_input_embeddings()(
1990
+ torch.tensor(image_token_id, dtype=torch.long, device=inputs_embeds.device)
1991
+ )
1992
+ )[..., 0]
1993
+ video_mask = (
1994
+ inputs_embeds
1995
+ == self.get_input_embeddings()(
1996
+ torch.tensor(video_token_id, dtype=torch.long, device=inputs_embeds.device)
1997
+ )
1998
+ )[..., 0]
1999
+ else:
2000
+ vision_start_mask = input_ids == vision_start_token_id
2001
+ image_mask = input_ids == image_token_id
2002
+ video_mask = input_ids == video_token_id
2003
+
2004
+ vision_first_mask = torch.roll(vision_start_mask, shifts=1, dims=1)
2005
+ image_nums = torch.sum(vision_first_mask & image_mask, dim=1)
2006
+ video_nums = torch.sum(vision_first_mask & video_mask, dim=1)
2007
+
2008
+ return image_nums, video_nums
2009
+
2010
+ def _expand_inputs_for_generation(
2011
+ self,
2012
+ expand_size: int = 1,
2013
+ is_encoder_decoder: bool = False,
2014
+ input_ids: torch.LongTensor | None = None,
2015
+ **model_kwargs,
2016
+ ) -> tuple[torch.LongTensor, dict[str, Any]]:
2017
+ # Overwritten -- Qwen3_5 use timestamps and remove second_per_grid_ts
2018
+ # Support for expanding tensors without a batch size dimension
2019
+ # e.g., pixel_values, image_grid_thw, pixel_values_videos, video_grid_thw
2020
+ # pixel_values.shape[0] is sum(seqlen_images for samples)
2021
+ # image_grid_thw.shape[0] is sum(num_images for samples)
2022
+
2023
+ if expand_size == 1:
2024
+ return input_ids, model_kwargs
2025
+
2026
+ visual_keys = ["pixel_values", "image_grid_thw", "pixel_values_videos", "video_grid_thw"]
2027
+
2028
+ def _expand_dict_for_generation_visual(dict_to_expand):
2029
+ image_grid_thw = model_kwargs.get("image_grid_thw", None)
2030
+ video_grid_thw = model_kwargs.get("video_grid_thw", None)
2031
+ image_nums, video_nums = self._get_image_nums_and_video_nums(
2032
+ input_ids, inputs_embeds=model_kwargs.get("inputs_embeds", None)
2033
+ )
2034
+
2035
+ # video_nums: (batch_size,)
2036
+ # since video_nums is the number of videos in the input dependent on the input_ids(vision_start),
2037
+ # but Qwen3_5 append vision_start to each frame of each video, so we need to recover the real video_nums according to video_grid_thw
2038
+ if video_grid_thw is not None:
2039
+ cumulative_frame_counts = torch.cumsum(video_grid_thw[:, 0], dim=0)
2040
+ cumulative_token_video_counts = torch.cumsum(video_nums, dim=0)
2041
+ # Find video boundaries in cumulative_frame_counts
2042
+ video_boundary_indices = torch.searchsorted(cumulative_frame_counts, cumulative_token_video_counts)
2043
+ # example: video_boundary_indices = [3, 5] means video_nums = [4, 2]
2044
+ video_nums = torch.diff(torch.cat([-video_boundary_indices.new_ones(1), video_boundary_indices]))
2045
+
2046
+ def _repeat_interleave_samples(x, lengths, repeat_times):
2047
+ samples = torch.split(x, lengths)
2048
+ repeat_args = [repeat_times] + [1] * (x.dim() - 1)
2049
+ result = torch.cat([sample.repeat(*repeat_args) for sample in samples], dim=0)
2050
+ return result
2051
+
2052
+ for key in dict_to_expand:
2053
+ if key == "pixel_values":
2054
+ # split images into samples
2055
+ samples = torch.split(image_grid_thw, list(image_nums))
2056
+ # compute the sequence length of images for each sample
2057
+ lengths = [torch.prod(sample, dim=1).sum() for sample in samples]
2058
+ dict_to_expand[key] = _repeat_interleave_samples(
2059
+ dict_to_expand[key], lengths=lengths, repeat_times=expand_size
2060
+ )
2061
+ elif key == "image_grid_thw":
2062
+ # get the num of images for each sample
2063
+ lengths = list(image_nums)
2064
+ dict_to_expand[key] = _repeat_interleave_samples(
2065
+ dict_to_expand[key], lengths=lengths, repeat_times=expand_size
2066
+ )
2067
+ elif key == "pixel_values_videos":
2068
+ samples = torch.split(video_grid_thw, list(video_nums))
2069
+ lengths = [torch.prod(sample, dim=1).sum() for sample in samples]
2070
+ dict_to_expand[key] = _repeat_interleave_samples(
2071
+ dict_to_expand[key], lengths=lengths, repeat_times=expand_size
2072
+ )
2073
+ elif key == "video_grid_thw":
2074
+ lengths = list(video_nums)
2075
+ dict_to_expand[key] = _repeat_interleave_samples(
2076
+ dict_to_expand[key], lengths=lengths, repeat_times=expand_size
2077
+ )
2078
+ return dict_to_expand
2079
+
2080
+ def _expand_dict_for_generation(dict_to_expand):
2081
+ for key in dict_to_expand:
2082
+ if key == "position_ids" and dict_to_expand[key].ndim == 3:
2083
+ dict_to_expand[key] = dict_to_expand[key].repeat_interleave(expand_size, dim=1)
2084
+ elif (
2085
+ dict_to_expand[key] is not None
2086
+ and isinstance(dict_to_expand[key], torch.Tensor)
2087
+ and key not in visual_keys
2088
+ ):
2089
+ dict_to_expand[key] = dict_to_expand[key].repeat_interleave(expand_size, dim=0)
2090
+ return dict_to_expand
2091
+
2092
+ model_kwargs = _expand_dict_for_generation_visual(model_kwargs)
2093
+
2094
+ if input_ids is not None:
2095
+ input_ids = input_ids.repeat_interleave(expand_size, dim=0)
2096
+
2097
+ model_kwargs = _expand_dict_for_generation(model_kwargs)
2098
+
2099
+ if is_encoder_decoder:
2100
+ if model_kwargs.get("encoder_outputs") is None:
2101
+ raise ValueError("If `is_encoder_decoder` is True, make sure that `encoder_outputs` is defined.")
2102
+ model_kwargs["encoder_outputs"] = _expand_dict_for_generation(model_kwargs["encoder_outputs"])
2103
+
2104
+ return input_ids, model_kwargs
2105
+
2106
+
2107
+ class Qwen3_5TextForSequenceClassification(GenericForSequenceClassification, Qwen3_5PreTrainedModel):
2108
+ config: Qwen3_5TextConfig
2109
+ input_modalities = ("text",)
2110
+
2111
+
2112
+ class Qwen3_5ForSequenceClassification(GenericForSequenceClassification, Qwen3_5PreTrainedModel):
2113
+ def forward(
2114
+ self,
2115
+ input_ids: torch.LongTensor = None,
2116
+ attention_mask: torch.Tensor | None = None,
2117
+ position_ids: torch.LongTensor | None = None,
2118
+ past_key_values: Cache | None = None,
2119
+ inputs_embeds: torch.FloatTensor | None = None,
2120
+ pixel_values: torch.Tensor | None = None,
2121
+ pixel_values_videos: torch.FloatTensor | None = None,
2122
+ image_grid_thw: torch.LongTensor | None = None,
2123
+ video_grid_thw: torch.LongTensor | None = None,
2124
+ mm_token_type_ids: torch.IntTensor | None = None,
2125
+ **kwargs: Unpack[TransformersKwargs],
2126
+ ) -> SequenceClassifierOutputWithPast:
2127
+ return super().forward(
2128
+ input_ids=input_ids,
2129
+ attention_mask=attention_mask,
2130
+ position_ids=position_ids,
2131
+ past_key_values=past_key_values,
2132
+ inputs_embeds=inputs_embeds,
2133
+ pixel_values=pixel_values,
2134
+ pixel_values_videos=pixel_values_videos,
2135
+ image_grid_thw=image_grid_thw,
2136
+ video_grid_thw=video_grid_thw,
2137
+ mm_token_type_ids=mm_token_type_ids,
2138
+ **kwargs,
2139
+ )
2140
+
2141
+
2142
+ __all__ = [
2143
+ "Qwen3_5VisionModel",
2144
+ "Qwen3_5TextModel",
2145
+ "Qwen3_5Model",
2146
+ "Qwen3_5ForCausalLM",
2147
+ "Qwen3_5TextForSequenceClassification",
2148
+ "Qwen3_5ForSequenceClassification",
2149
+ "Qwen3_5ForTokenClassification",
2150
+ "Qwen3_5ForConditionalGeneration",
2151
+ "Qwen3_5PreTrainedModel",
2152
+ ]
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/qwen3_5/tokenization_qwen3_5.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2024 The Qwen team, Alibaba Group and The HuggingFace Inc. team. All rights reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """Tokenization classes for Qwen3.5."""
15
+
16
+ from tokenizers import Regex, Tokenizer, decoders, normalizers, pre_tokenizers
17
+ from tokenizers.models import BPE
18
+
19
+ from ...tokenization_utils_tokenizers import TokenizersBackend
20
+ from ...utils import logging
21
+
22
+
23
+ logger = logging.get_logger(__name__)
24
+
25
+ PRETOKENIZE_REGEX = r"""(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?[\p{L}\p{M}]+|\p{N}| ?[^\s\p{L}\p{M}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+"""
26
+
27
+
28
+ class Qwen3_5Tokenizer(TokenizersBackend):
29
+ model_input_names = ["input_ids", "attention_mask"]
30
+ model = BPE
31
+
32
+ def __init__(
33
+ self,
34
+ vocab: str | dict[str, int] | None = None,
35
+ merges: str | list[str] | None = None,
36
+ vocab_file=None,
37
+ merges_file=None,
38
+ unk_token: str = "<|endoftext|>",
39
+ bos_token=None,
40
+ eos_token: str = "<|endoftext|>",
41
+ pad_token: str = "<|endoftext|>",
42
+ add_prefix_space=None,
43
+ **kwargs,
44
+ ):
45
+ self.add_prefix_space = add_prefix_space if add_prefix_space is not None else False
46
+ self._vocab = (
47
+ vocab
48
+ if vocab is not None
49
+ else {
50
+ "<|endoftext|>": 0,
51
+ }
52
+ )
53
+ self._merges = merges or []
54
+ self._tokenizer = Tokenizer(
55
+ BPE(
56
+ vocab=self._vocab,
57
+ merges=self._merges,
58
+ dropout=None,
59
+ unk_token=None,
60
+ continuing_subword_prefix="",
61
+ end_of_word_suffix="",
62
+ fuse_unk=False,
63
+ byte_fallback=False,
64
+ )
65
+ )
66
+ self._tokenizer.decoder = decoders.ByteLevel()
67
+ self._tokenizer.normalizer = normalizers.NFC()
68
+ self._tokenizer.pre_tokenizer = pre_tokenizers.Sequence(
69
+ [
70
+ pre_tokenizers.Split(
71
+ Regex(PRETOKENIZE_REGEX),
72
+ behavior="isolated",
73
+ invert=False,
74
+ ),
75
+ pre_tokenizers.ByteLevel(
76
+ add_prefix_space=self.add_prefix_space,
77
+ use_regex=False,
78
+ ),
79
+ ]
80
+ )
81
+
82
+ super().__init__(
83
+ vocab_file=vocab_file,
84
+ merges_file=merges_file,
85
+ unk_token=unk_token,
86
+ bos_token=bos_token,
87
+ eos_token=eos_token,
88
+ pad_token=pad_token,
89
+ add_prefix_space=add_prefix_space,
90
+ **kwargs,
91
+ )
92
+
93
+
94
+ __all__ = ["Qwen3_5Tokenizer"]
LTA_openwebtext_dualt/mini_owt_logdirichlet/.venv_qwen35_uv/lib/python3.12/site-packages/transformers/models/sam2/modeling_sam2.py ADDED
@@ -0,0 +1,1622 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
2
+ # This file was automatically generated from src/transformers/models/sam2/modular_sam2.py.
3
+ # Do NOT edit this file manually as any edits will be overwritten by the generation of
4
+ # the file from the modular. If any change should be done, please apply the change to the
5
+ # modular_sam2.py file directly. One of our CI enforces this.
6
+ # 🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨🚨
7
+ # Copyright 2025 The Meta AI Authors and The HuggingFace Team. All rights reserved.
8
+ #
9
+ # Licensed under the Apache License, Version 2.0 (the "License");
10
+ # you may not use this file except in compliance with the License.
11
+ # You may obtain a copy of the License at
12
+ #
13
+ # http://www.apache.org/licenses/LICENSE-2.0
14
+ #
15
+ # Unless required by applicable law or agreed to in writing, software
16
+ # distributed under the License is distributed on an "AS IS" BASIS,
17
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ # See the License for the specific language governing permissions and
19
+ # limitations under the License.
20
+
21
+ import math
22
+ from collections.abc import Callable
23
+ from dataclasses import dataclass
24
+
25
+ import numpy as np
26
+ import torch
27
+ import torch.nn as nn
28
+ import torch.nn.functional as F
29
+ from torch import Tensor
30
+
31
+ from ... import initialization as init
32
+ from ...activations import ACT2FN
33
+ from ...modeling_layers import GradientCheckpointingLayer
34
+ from ...modeling_outputs import BaseModelOutput, BaseModelOutputWithPooling
35
+ from ...modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
36
+ from ...processing_utils import Unpack
37
+ from ...pytorch_utils import compile_compatible_method_lru_cache
38
+ from ...utils import ModelOutput, auto_docstring, can_return_tuple, logging
39
+ from ...utils.generic import TransformersKwargs, is_flash_attention_requested, merge_with_config_defaults
40
+ from ...utils.output_capturing import OutputRecorder, capture_outputs
41
+ from ..auto import AutoModel
42
+ from .configuration_sam2 import (
43
+ Sam2Config,
44
+ Sam2HieraDetConfig,
45
+ Sam2MaskDecoderConfig,
46
+ Sam2PromptEncoderConfig,
47
+ Sam2VisionConfig,
48
+ )
49
+
50
+
51
+ logger = logging.get_logger(__name__)
52
+
53
+
54
+ @auto_docstring(custom_intro="Base class for the vision encoder's outputs.")
55
+ @dataclass
56
+ class Sam2VisionEncoderOutput(BaseModelOutputWithPooling):
57
+ r"""
58
+ last_hidden_state (`torch.FloatTensor` of shape `(batch_size, height, width, hidden_size)`):
59
+ Sequence of hidden-states at the output of the last layer of the model.
60
+ hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True` is passed or when `config.output_hidden_states=True`):
61
+ Tuple of `torch.FloatTensor` (one for the output of the embeddings, if the model has an embedding layer, +
62
+ one for the output of each stage) of shape `(batch_size, height, width, hidden_size)`. Hidden-states of the
63
+ model at the output of each stage.
64
+ attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True` is passed or when `config.output_attentions=True`):
65
+ Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length,
66
+ sequence_length)`. Attentions weights after the attention softmax, used to compute the weighted average in
67
+ the self-attention heads.
68
+ fpn_hidden_states (`tuple(torch.FloatTensor)`):
69
+ Tuple of `torch.FloatTensor` (one for each feature level, from high to low resolution) of shape
70
+ `(batch_size, hidden_size, height, width)`. Feature maps from the Feature Pyramid Network neck.
71
+ fpn_position_encoding (`tuple(torch.FloatTensor)`):
72
+ Tuple of `torch.FloatTensor` (one for each feature level, from high to low resolution) of shape
73
+ `(batch_size, hidden_size, height, width)`. Positional encodings corresponding to the `fpn_hidden_states`.
74
+ """
75
+
76
+ fpn_hidden_states: torch.FloatTensor | None = None
77
+ fpn_position_encoding: torch.FloatTensor | None = None
78
+
79
+
80
+ @auto_docstring(custom_intro="Base class for the Sam2 model's output.")
81
+ @dataclass
82
+ class Sam2ImageSegmentationOutput(ModelOutput):
83
+ r"""
84
+ iou_scores (`torch.FloatTensor` of shape `(batch_size, point_batch_size, num_masks)`):
85
+ The Intersection over Union (IoU) scores of the predicted masks.
86
+ pred_masks (`torch.FloatTensor` of shape `(batch_size, point_batch_size, num_masks, height, width)`):
87
+ The predicted low-resolution masks. This is an alias for `low_res_masks`. These masks need to be post-processed
88
+ by the processor to be brought to the original image size.
89
+ object_score_logits (`torch.FloatTensor` of shape `(batch_size, point_batch_size, 1)`):
90
+ Logits for the object score, indicating if an object is present.
91
+ image_embeddings (`tuple(torch.FloatTensor)`):
92
+ The features from the FPN, which are used by the mask decoder. This is a tuple of `torch.FloatTensor` where each
93
+ tensor has shape `(batch_size, channels, height, width)`.
94
+ vision_hidden_states (`tuple(torch.FloatTensor)`, *optional*, returned when `output_hidden_states=True`):
95
+ Tuple of `torch.FloatTensor` (one for the output of each stage) of shape `(batch_size, height, width, hidden_size)`.
96
+ Hidden-states of the vision model at the output of each stage.
97
+ vision_attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True`):
98
+ Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length, sequence_length)`.
99
+ Attentions weights of the vision model.
100
+ mask_decoder_attentions (`tuple(torch.FloatTensor)`, *optional*, returned when `output_attentions=True`):
101
+ Tuple of `torch.FloatTensor` (one for each layer) of shape `(batch_size, num_heads, sequence_length, sequence_length)`.
102
+ Attentions weights of the mask decoder.
103
+ """
104
+
105
+ iou_scores: torch.FloatTensor | None = None
106
+ pred_masks: torch.FloatTensor | None = None
107
+ object_score_logits: torch.FloatTensor | None = None
108
+ image_embeddings: tuple[torch.FloatTensor, ...] = None
109
+ vision_hidden_states: tuple[torch.FloatTensor, ...] | None = None
110
+ vision_attentions: tuple[torch.FloatTensor, ...] | None = None
111
+ mask_decoder_attentions: tuple[torch.FloatTensor, ...] | None = None
112
+
113
+
114
+ class Sam2PatchEmbeddings(nn.Module):
115
+ r"""
116
+ Turns pixel values into patch embeddings for transformer consumption.
117
+
118
+ Args:
119
+ pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, height, width)`):
120
+ Pixel values. Pixel values can be obtained using
121
+ [`AutoImageProcessor`]. See [`Sam2ImageProcessor.__call__`] for details.
122
+
123
+ Returns:
124
+ embeddings (`torch.FloatTensor`):
125
+ Patch embeddings depend on image_size, patch_kernel_size, patch_stride and patch_padding
126
+ """
127
+
128
+ def __init__(self, config: Sam2HieraDetConfig):
129
+ super().__init__()
130
+ num_channels = config.num_channels
131
+ hidden_size = config.hidden_size
132
+
133
+ self.projection = nn.Conv2d(
134
+ num_channels,
135
+ hidden_size,
136
+ kernel_size=config.patch_kernel_size,
137
+ stride=config.patch_stride,
138
+ padding=config.patch_padding,
139
+ )
140
+
141
+ def forward(self, pixel_values):
142
+ _, num_channels, height, width = pixel_values.shape
143
+ embeddings = self.projection(pixel_values.to(self.projection.weight.dtype)).permute(0, 2, 3, 1)
144
+ return embeddings
145
+
146
+
147
+ class Sam2SinePositionEmbedding(nn.Module):
148
+ """
149
+ This is a more standard version of the position embedding, very similar to the one used by the Attention is all you
150
+ need paper, generalized to work on images.
151
+ """
152
+
153
+ def __init__(
154
+ self,
155
+ num_position_features: int = 64,
156
+ temperature: int = 10000,
157
+ normalize: bool = False,
158
+ scale: float | None = None,
159
+ ):
160
+ super().__init__()
161
+ if scale is not None and normalize is False:
162
+ raise ValueError("normalize should be True if scale is passed")
163
+ self.num_position_features = num_position_features
164
+ self.temperature = temperature
165
+ self.normalize = normalize
166
+ self.scale = 2 * math.pi if scale is None else scale
167
+
168
+ @staticmethod
169
+ @compile_compatible_method_lru_cache(maxsize=1)
170
+ def build_sine_position_embedding(
171
+ shape: torch.Size,
172
+ device: torch.device | str,
173
+ dtype: torch.dtype,
174
+ num_position_features: int,
175
+ normalize: bool = False,
176
+ scale: float | None = None,
177
+ temperature: int = 10000,
178
+ mask: torch.Tensor | None = None,
179
+ ) -> torch.Tensor:
180
+ if mask is None:
181
+ mask = torch.ones((shape[0], shape[2], shape[3]), device=device, dtype=torch.bool)
182
+ y_embed = mask.cumsum(1, dtype=dtype)
183
+ x_embed = mask.cumsum(2, dtype=dtype)
184
+ if normalize:
185
+ eps = 1e-6
186
+ y_embed = y_embed / (y_embed[:, -1:, :] + eps) * scale
187
+ x_embed = x_embed / (x_embed[:, :, -1:] + eps) * scale
188
+
189
+ dim_t = torch.arange(num_position_features, dtype=torch.int64, device=device).to(dtype)
190
+ dim_t = temperature ** (2 * torch.div(dim_t, 2, rounding_mode="floor") / num_position_features)
191
+
192
+ pos_x = x_embed[:, :, :, None] / dim_t
193
+ pos_y = y_embed[:, :, :, None] / dim_t
194
+ pos_x = torch.stack((pos_x[:, :, :, 0::2].sin(), pos_x[:, :, :, 1::2].cos()), dim=4).flatten(3)
195
+ pos_y = torch.stack((pos_y[:, :, :, 0::2].sin(), pos_y[:, :, :, 1::2].cos()), dim=4).flatten(3)
196
+ pos = torch.cat((pos_y, pos_x), dim=3).permute(0, 3, 1, 2)
197
+ return pos
198
+
199
+ def forward(
200
+ self,
201
+ shape: torch.Size,
202
+ device: torch.device | str,
203
+ dtype: torch.dtype,
204
+ mask: torch.Tensor | None = None,
205
+ ) -> torch.Tensor:
206
+ return self.build_sine_position_embedding(
207
+ shape, device, dtype, self.num_position_features, self.normalize, self.scale, self.temperature, mask
208
+ )
209
+
210
+
211
+ class Sam2VisionNeck(nn.Module):
212
+ def __init__(self, config: Sam2VisionConfig):
213
+ super().__init__()
214
+ self.config = config
215
+
216
+ self.position_encoding = Sam2SinePositionEmbedding(
217
+ num_position_features=config.fpn_hidden_size // 2, normalize=True
218
+ )
219
+ self.convs = nn.ModuleList()
220
+ for in_channels in config.backbone_channel_list:
221
+ self.convs.append(
222
+ nn.Conv2d(
223
+ in_channels=in_channels,
224
+ out_channels=config.fpn_hidden_size,
225
+ kernel_size=config.fpn_kernel_size,
226
+ stride=config.fpn_stride,
227
+ padding=config.fpn_padding,
228
+ ),
229
+ )
230
+ self.fpn_top_down_levels = config.fpn_top_down_levels
231
+
232
+ def forward(self, hidden_states: torch.Tensor) -> tuple[tuple[torch.Tensor, ...], tuple[torch.Tensor, ...]]:
233
+ fpn_hidden_states = ()
234
+ fpn_position_encoding = ()
235
+
236
+ # forward in top-down order (from low to high resolution)
237
+ n = len(self.convs) - 1
238
+ for i in range(n, -1, -1):
239
+ lateral_features = hidden_states[i].permute(0, 3, 1, 2)
240
+ lateral_features = self.convs[n - i](lateral_features.to(self.convs[i].weight.dtype))
241
+ if i not in self.fpn_top_down_levels or i == n:
242
+ prev_features = lateral_features
243
+ else:
244
+ top_down_features = F.interpolate(
245
+ prev_features.to(dtype=torch.float32),
246
+ scale_factor=2.0,
247
+ mode="nearest",
248
+ align_corners=None,
249
+ antialias=False,
250
+ ).to(lateral_features.dtype)
251
+ prev_features = lateral_features + top_down_features
252
+
253
+ prev_position_encoding = self.position_encoding(
254
+ prev_features.shape, prev_features.device, prev_features.dtype
255
+ ).to(prev_features.dtype)
256
+
257
+ fpn_hidden_states += (prev_features,)
258
+ fpn_position_encoding += (prev_position_encoding,)
259
+
260
+ return fpn_hidden_states, fpn_position_encoding
261
+
262
+
263
+ def eager_attention_forward(
264
+ module: nn.Module,
265
+ query: torch.Tensor,
266
+ key: torch.Tensor,
267
+ value: torch.Tensor,
268
+ attention_mask: torch.Tensor | None,
269
+ scaling: float,
270
+ dropout: float = 0.0,
271
+ **kwargs,
272
+ ):
273
+ attn_weights = torch.matmul(query, key.transpose(2, 3)) * scaling
274
+ if attention_mask is not None:
275
+ attn_weights = attn_weights + attention_mask
276
+
277
+ attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
278
+ attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
279
+ attn_output = torch.matmul(attn_weights, value)
280
+ attn_output = attn_output.transpose(1, 2).contiguous()
281
+
282
+ return attn_output, attn_weights
283
+
284
+
285
+ def do_pool(x: torch.Tensor, query_stride: int | None = None) -> torch.Tensor:
286
+ if query_stride is None:
287
+ return x
288
+ # (B, H, W, C) -> (B, C, H, W)
289
+ x = x.permute(0, 3, 1, 2)
290
+ x = nn.functional.max_pool2d(x, kernel_size=query_stride, stride=query_stride, ceil_mode=False)
291
+ # (B, C, H', W') -> (B, H', W', C)
292
+ x = x.permute(0, 2, 3, 1)
293
+ return x
294
+
295
+
296
+ class Sam2MultiScaleAttention(nn.Module):
297
+ def __init__(
298
+ self,
299
+ config: Sam2HieraDetConfig,
300
+ dim: int,
301
+ dim_out: int,
302
+ num_attention_heads: int,
303
+ query_stride: tuple[int, int] | None = None,
304
+ ):
305
+ super().__init__()
306
+
307
+ self.config = config
308
+
309
+ self.dim = dim
310
+ self.dim_out = dim_out
311
+ self.query_stride = query_stride
312
+
313
+ self.num_attention_heads = num_attention_heads
314
+ head_dim = dim_out // num_attention_heads
315
+ self.scale = head_dim**-0.5
316
+ self.qkv = nn.Linear(dim, dim_out * 3)
317
+ self.proj = nn.Linear(dim_out, dim_out)
318
+
319
+ self.is_causal = False
320
+
321
+ def forward(self, hidden_states: torch.Tensor, **kwargs) -> torch.Tensor:
322
+ batch_size, height, width, _ = hidden_states.shape
323
+ # qkv with shape (B, H * W, 3, nHead, C)
324
+ qkv = self.qkv(hidden_states).reshape(batch_size, height * width, 3, self.num_attention_heads, -1)
325
+ # q, k, v with shape (B, H * W, nheads, C)
326
+ query, key, value = torch.unbind(qkv, 2)
327
+
328
+ attn_weights = (query * self.scale) @ key.transpose(-2, -1)
329
+ attn_weights = torch.nn.functional.softmax(attn_weights, dtype=torch.float32, dim=-1).to(query.dtype)
330
+
331
+ # Q pooling (for downsample at stage changes)
332
+ if self.query_stride:
333
+ query = do_pool(query.reshape(batch_size, height, width, -1), self.query_stride)
334
+ height, width = query.shape[1:3] # downsampled shape
335
+ query = query.reshape(batch_size, height * width, self.num_attention_heads, -1)
336
+
337
+ # transpose query, key, value to (B, nHead, H * W, C)
338
+ query = query.transpose(1, 2)
339
+ key = key.transpose(1, 2)
340
+ value = value.transpose(1, 2)
341
+
342
+ attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
343
+ self.config._attn_implementation, eager_attention_forward
344
+ )
345
+ attn_output, _ = attention_interface(
346
+ self,
347
+ query,
348
+ key,
349
+ value,
350
+ attention_mask=None,
351
+ is_causal=self.is_causal,
352
+ scaling=self.scale,
353
+ **kwargs,
354
+ )
355
+ attn_output = attn_output.reshape(batch_size, height, width, -1)
356
+
357
+ attn_output = self.proj(attn_output)
358
+
359
+ return attn_output
360
+
361
+
362
+ class Sam2FeedForward(nn.Module):
363
+ def __init__(
364
+ self,
365
+ input_dim: int,
366
+ hidden_dim: int,
367
+ output_dim: int,
368
+ num_layers: int,
369
+ activation: str = "relu",
370
+ sigmoid_output: bool = False,
371
+ ):
372
+ super().__init__()
373
+ self.num_layers = num_layers
374
+ self.activation = ACT2FN[activation]
375
+ self.proj_in = nn.Linear(input_dim, hidden_dim)
376
+ self.proj_out = nn.Linear(hidden_dim, output_dim)
377
+ self.layers = nn.ModuleList([nn.Linear(hidden_dim, hidden_dim) for _ in range(num_layers - 2)])
378
+ self.sigmoid_output = sigmoid_output
379
+
380
+ def forward(self, hidden_states):
381
+ hidden_states = self.proj_in(hidden_states)
382
+ hidden_states = self.activation(hidden_states)
383
+ for layer in self.layers:
384
+ hidden_states = self.activation(layer(hidden_states))
385
+
386
+ hidden_states = self.proj_out(hidden_states)
387
+ if self.sigmoid_output:
388
+ hidden_states = F.sigmoid(hidden_states)
389
+ return hidden_states
390
+
391
+
392
+ def window_partition(hidden_state, window_size):
393
+ """
394
+ Partition into non-overlapping windows with padding if needed.
395
+
396
+ Args:
397
+ hidden_state (`torch.Tensor`):
398
+ Input tokens with [batch_size, height, width, num_channels].
399
+ window_size (`int`):
400
+ Window size.
401
+
402
+ Returns:
403
+ `tuple(torch.FloatTensor)` comprising various elements:
404
+ - windows: windows after partition with [batch_size * num_windows, window_size, window_size, num_channels].
405
+ - (padded_height, padded_width): padded height and width before partition
406
+ """
407
+ batch_size, height, width, num_channels = hidden_state.shape
408
+
409
+ pad_height = (window_size - height % window_size) % window_size
410
+ pad_width = (window_size - width % window_size) % window_size
411
+
412
+ # Noop in case pad_width == 0 and pad_height == 0.
413
+ hidden_state = nn.functional.pad(hidden_state, (0, 0, 0, pad_width, 0, pad_height))
414
+
415
+ padded_height, padded_width = height + pad_height, width + pad_width
416
+
417
+ hidden_state = hidden_state.view(
418
+ batch_size, padded_height // window_size, window_size, padded_width // window_size, window_size, num_channels
419
+ )
420
+ windows = hidden_state.permute(0, 1, 3, 2, 4, 5).contiguous().view(-1, window_size, window_size, num_channels)
421
+ return windows, (padded_height, padded_width)
422
+
423
+
424
+ def window_unpartition(windows, window_size, pad_height_width, height_width):
425
+ """
426
+ Window unpartition into original sequences and removing padding.
427
+
428
+ Args:
429
+ windows (`torch.Tensor`):
430
+ Input tokens with [batch_size * num_windows, window_size, window_size, num_channels].
431
+ window_size (`int`):
432
+ Window size.
433
+ pad_height_width (`tuple[int]`):
434
+ Padded height and width (padded_height, padded_width).
435
+ height_width (`tuple[int]`):
436
+ Original height and width before padding.
437
+
438
+ Returns:
439
+ hidden_state: unpartitioned sequences with [batch_size, height, width, num_channels].
440
+ """
441
+ padded_height, padded_width = pad_height_width
442
+ height, width = height_width
443
+ batch_size = windows.shape[0] // (padded_height * padded_width // window_size // window_size)
444
+ hidden_state = windows.view(
445
+ batch_size, padded_height // window_size, padded_width // window_size, window_size, window_size, -1
446
+ )
447
+ hidden_state = hidden_state.permute(0, 1, 3, 2, 4, 5).contiguous()
448
+ hidden_state = hidden_state.view(batch_size, padded_height, padded_width, -1)
449
+
450
+ # We always have height <= padded_height and width <= padded_width
451
+ hidden_state = hidden_state[:, :height, :width, :].contiguous()
452
+ return hidden_state
453
+
454
+
455
+ class Sam2MultiScaleBlock(GradientCheckpointingLayer):
456
+ def __init__(
457
+ self,
458
+ config: Sam2HieraDetConfig,
459
+ stage_idx: int,
460
+ block_idx: int,
461
+ total_block_idx: int,
462
+ ):
463
+ super().__init__()
464
+
465
+ # take embed dim from previous stage if first block of stage
466
+ self.dim = (
467
+ config.embed_dim_per_stage[stage_idx - 1]
468
+ if stage_idx > 0 and block_idx == 0
469
+ else config.embed_dim_per_stage[stage_idx]
470
+ )
471
+ self.dim_out = config.embed_dim_per_stage[stage_idx]
472
+ self.layer_norm1 = nn.LayerNorm(self.dim, eps=config.layer_norm_eps)
473
+ # take window size from previous stage if first block of stage
474
+ self.window_size = (
475
+ config.window_size_per_stage[stage_idx - 1]
476
+ if stage_idx > 0 and block_idx == 0
477
+ else config.window_size_per_stage[stage_idx]
478
+ )
479
+ self.window_size = 0 if total_block_idx in config.global_attention_blocks else self.window_size
480
+ # use query stride for first block of stage if stage is a query pool stage
481
+ self.query_stride = (
482
+ config.query_stride if 0 < stage_idx <= config.num_query_pool_stages and block_idx == 0 else None
483
+ )
484
+
485
+ self.attn = Sam2MultiScaleAttention(
486
+ config,
487
+ self.dim,
488
+ self.dim_out,
489
+ num_attention_heads=config.num_attention_heads_per_stage[stage_idx],
490
+ query_stride=self.query_stride,
491
+ )
492
+ self.layer_norm2 = nn.LayerNorm(self.dim_out, eps=config.layer_norm_eps)
493
+ self.mlp = Sam2FeedForward(
494
+ self.dim_out,
495
+ int(self.dim_out * config.mlp_ratio),
496
+ self.dim_out,
497
+ num_layers=2,
498
+ activation=config.hidden_act,
499
+ )
500
+ if self.dim != self.dim_out:
501
+ self.proj = nn.Linear(self.dim, self.dim_out)
502
+
503
+ def forward(
504
+ self,
505
+ hidden_states: torch.Tensor,
506
+ **kwargs: Unpack[TransformersKwargs],
507
+ ) -> torch.FloatTensor:
508
+ residual = hidden_states # batch_size, height, width, channel
509
+
510
+ hidden_states = self.layer_norm1(hidden_states)
511
+
512
+ # Skip connection
513
+ if self.dim != self.dim_out:
514
+ residual = do_pool(self.proj(hidden_states), self.query_stride)
515
+
516
+ # Window partition
517
+ window_size = self.window_size
518
+ if self.window_size > 0:
519
+ H, W = hidden_states.shape[1], hidden_states.shape[2]
520
+ hidden_states, pad_hw = window_partition(hidden_states, window_size)
521
+
522
+ # Window Attention + Q Pooling (if stage change)
523
+ attn_output = self.attn(
524
+ hidden_states=hidden_states,
525
+ **kwargs,
526
+ )
527
+ hidden_states = attn_output
528
+ if self.query_stride:
529
+ # Shapes have changed due to Q pooling
530
+ window_size = self.window_size // self.query_stride[0]
531
+ H, W = residual.shape[1:3]
532
+
533
+ pad_h = (window_size - H % window_size) % window_size
534
+ pad_w = (window_size - W % window_size) % window_size
535
+ pad_hw = (H + pad_h, W + pad_w)
536
+
537
+ # Reverse window partition
538
+ if self.window_size > 0:
539
+ hidden_states = window_unpartition(hidden_states, window_size, pad_hw, (H, W))
540
+
541
+ hidden_states = residual + hidden_states
542
+ layernorm_output = self.layer_norm2(hidden_states)
543
+ hidden_states = hidden_states + self.mlp(layernorm_output)
544
+
545
+ return hidden_states
546
+
547
+
548
+ @auto_docstring(
549
+ custom_intro="""
550
+ Hiera model's outputs that also contains a pooling of the last hidden states.
551
+ """
552
+ )
553
+ @dataclass
554
+ class Sam2HieraDetModelOutput(ModelOutput):
555
+ r"""
556
+ last_hidden_state (`torch.FloatTensor` of shape `(batch_size, height, width, hidden_size)`):
557
+ hidden-states at the output of the last layer of the model.
558
+ intermediate_hidden_states (`tuple[torch.FloatTensor]` of shape `(batch_size, height, width, hidden_size)`):
559
+ Sequence of hidden-states at the output of the intermediate layers of the model.
560
+ """
561
+
562
+ last_hidden_state: torch.FloatTensor | None = None
563
+ intermediate_hidden_states: tuple[torch.FloatTensor, ...] | None = None
564
+ hidden_states: tuple[torch.FloatTensor, ...] | None = None
565
+ attentions: tuple[torch.FloatTensor, ...] | None = None
566
+
567
+
568
+ @auto_docstring
569
+ class Sam2PreTrainedModel(PreTrainedModel):
570
+ config_class = Sam2Config
571
+ base_model_prefix = "sam2"
572
+ main_input_name = "pixel_values"
573
+ input_modalities = ("image",)
574
+ _supports_sdpa = True
575
+ _supports_flash_attn = True
576
+ _supports_attention_backend = True
577
+ _keys_to_ignore_on_load_unexpected = [
578
+ r"^memory_.*",
579
+ r"^mask_downsample.*",
580
+ r"^object_pointer_proj.*",
581
+ r"^temporal_positional_encoding_projection_layer.*",
582
+ "no_memory_positional_encoding",
583
+ "no_object_pointer",
584
+ "occlusion_spatial_embedding_parameter",
585
+ ]
586
+
587
+ @torch.no_grad()
588
+ def _init_weights(self, module):
589
+ super()._init_weights(module)
590
+ if isinstance(module, Sam2HieraDetModel):
591
+ if module.pos_embed is not None:
592
+ init.zeros_(module.pos_embed)
593
+ if module.pos_embed_window is not None:
594
+ init.zeros_(module.pos_embed_window)
595
+ elif isinstance(module, Sam2PositionalEmbedding):
596
+ init.normal_(module.positional_embedding, std=module.scale)
597
+ elif isinstance(module, Sam2Model):
598
+ if module.no_memory_embedding is not None:
599
+ init.zeros_(module.no_memory_embedding)
600
+
601
+
602
+ class Sam2HieraDetModel(Sam2PreTrainedModel):
603
+ config_class = Sam2HieraDetConfig
604
+ main_input_name = "pixel_values"
605
+ _can_record_outputs = {
606
+ "hidden_states": Sam2MultiScaleBlock,
607
+ "attentions": Sam2MultiScaleAttention,
608
+ }
609
+
610
+ def __init__(self, config: Sam2HieraDetConfig):
611
+ super().__init__(config)
612
+
613
+ self.patch_embed = Sam2PatchEmbeddings(config)
614
+ # Windowed positional embedding (https://huggingface.co/papers/2311.05613)
615
+ self.pos_embed = nn.Parameter(
616
+ torch.zeros(1, config.hidden_size, *config.window_positional_embedding_background_size)
617
+ )
618
+ self.pos_embed_window = nn.Parameter(
619
+ torch.zeros(1, config.hidden_size, config.window_size_per_stage[0], config.window_size_per_stage[0])
620
+ )
621
+ self.stage_ends = (np.cumsum(config.blocks_per_stage) - 1).tolist()
622
+ self.blocks = nn.ModuleList()
623
+ total_block_idx = 0
624
+ for stage_idx, blocks_per_stage in enumerate(config.blocks_per_stage):
625
+ for block_idx in range(blocks_per_stage):
626
+ block = Sam2MultiScaleBlock(
627
+ config=config, stage_idx=stage_idx, block_idx=block_idx, total_block_idx=total_block_idx
628
+ )
629
+ self.blocks.append(block)
630
+ total_block_idx += 1
631
+
632
+ self.post_init()
633
+
634
+ def get_input_embeddings(self):
635
+ return self.patch_embed
636
+
637
+ def _get_pos_embed(self, hw: tuple[int, int]) -> torch.Tensor:
638
+ h, w = hw
639
+ window_embed = self.pos_embed_window
640
+ pos_embed = F.interpolate(self.pos_embed, size=(h, w), mode="bicubic")
641
+ pos_embed = pos_embed + window_embed.tile([x // y for x, y in zip(pos_embed.shape, window_embed.shape)])
642
+ pos_embed = pos_embed.permute(0, 2, 3, 1)
643
+ return pos_embed
644
+
645
+ @merge_with_config_defaults
646
+ @capture_outputs
647
+ def forward(
648
+ self,
649
+ pixel_values: torch.FloatTensor | None = None,
650
+ **kwargs: Unpack[TransformersKwargs],
651
+ ) -> tuple | Sam2HieraDetModelOutput:
652
+ if pixel_values is None:
653
+ raise ValueError("You have to specify pixel_values")
654
+
655
+ hidden_states = self.patch_embed(pixel_values)
656
+ hidden_states = hidden_states + self._get_pos_embed(hidden_states.shape[1:3])
657
+
658
+ intermediate_hidden_states = ()
659
+ for i, block_module in enumerate(self.blocks):
660
+ hidden_states = block_module(hidden_states, **kwargs)
661
+
662
+ if i in self.stage_ends:
663
+ intermediate_hidden_states = intermediate_hidden_states + (hidden_states,)
664
+
665
+ return Sam2HieraDetModelOutput(
666
+ last_hidden_state=hidden_states,
667
+ intermediate_hidden_states=intermediate_hidden_states,
668
+ )
669
+
670
+
671
+ @auto_docstring(
672
+ custom_intro="""
673
+ The vision model from Sam without any head or projection on top.
674
+ """
675
+ )
676
+ class Sam2VisionModel(Sam2PreTrainedModel):
677
+ config_class = Sam2VisionConfig
678
+ main_input_name = "pixel_values"
679
+ _can_record_outputs = {
680
+ "hidden_states": Sam2MultiScaleBlock,
681
+ "attentions": Sam2MultiScaleAttention,
682
+ }
683
+
684
+ def __init__(self, config: Sam2VisionConfig):
685
+ super().__init__(config)
686
+ self.config = config
687
+
688
+ self.backbone = AutoModel.from_config(config.backbone_config)
689
+
690
+ self.neck = Sam2VisionNeck(config)
691
+ self.num_feature_levels = config.num_feature_levels
692
+
693
+ self.post_init()
694
+
695
+ def get_input_embeddings(self):
696
+ return self.backbone.get_input_embeddings()
697
+
698
+ @can_return_tuple
699
+ def forward(
700
+ self,
701
+ pixel_values: torch.FloatTensor | None = None,
702
+ **kwargs: Unpack[TransformersKwargs],
703
+ ) -> tuple | Sam2VisionEncoderOutput:
704
+ if pixel_values is None:
705
+ raise ValueError("You have to specify pixel_values")
706
+
707
+ # Forward through backbone
708
+ backbone_output = self.backbone(pixel_values, **kwargs)
709
+ hidden_states = backbone_output.last_hidden_state
710
+ intermediate_hidden_states = backbone_output.intermediate_hidden_states
711
+
712
+ fpn_hidden_states, fpn_position_encoding = self.neck(intermediate_hidden_states)
713
+ # Select last `num_feature_levels` feature levels from FPN and reverse order to get features from high to low resolution
714
+ fpn_hidden_states = fpn_hidden_states[-self.num_feature_levels :][::-1]
715
+ fpn_position_encoding = fpn_position_encoding[-self.num_feature_levels :][::-1]
716
+
717
+ return Sam2VisionEncoderOutput(
718
+ last_hidden_state=hidden_states,
719
+ fpn_hidden_states=fpn_hidden_states,
720
+ fpn_position_encoding=fpn_position_encoding,
721
+ hidden_states=backbone_output.hidden_states,
722
+ attentions=backbone_output.attentions,
723
+ )
724
+
725
+
726
+ class Sam2PositionalEmbedding(nn.Module):
727
+ def __init__(self, config: Sam2PromptEncoderConfig):
728
+ super().__init__()
729
+ self.scale = config.scale
730
+ positional_embedding = self.scale * torch.randn((2, config.hidden_size // 2))
731
+ self.register_buffer("positional_embedding", positional_embedding)
732
+
733
+ def forward(self, input_coords, input_shape=None):
734
+ """Positionally encode points that are normalized to [0,1]."""
735
+ coordinates = input_coords.clone()
736
+
737
+ if input_shape is not None:
738
+ coordinates[:, :, :, 0] = coordinates[:, :, :, 0] / input_shape[1]
739
+ coordinates[:, :, :, 1] = coordinates[:, :, :, 1] / input_shape[0]
740
+ coordinates.to(torch.float32)
741
+
742
+ # assuming coords are in [0, 1]^2 square and have d_1 x ... x d_n x 2 shape
743
+ coordinates = 2 * coordinates - 1
744
+ coordinates = coordinates.to(self.positional_embedding.dtype)
745
+ coordinates = coordinates @ self.positional_embedding
746
+ coordinates = 2 * np.pi * coordinates
747
+ # outputs d_1 x ... x d_n x channel shape
748
+ return torch.cat([torch.sin(coordinates), torch.cos(coordinates)], dim=-1)
749
+
750
+
751
+ class Sam2MaskEmbedding(nn.Module):
752
+ def __init__(self, config: Sam2PromptEncoderConfig):
753
+ super().__init__()
754
+ self.mask_input_channels = config.mask_input_channels // 4
755
+ self.activation = ACT2FN[config.hidden_act]
756
+ self.conv1 = nn.Conv2d(1, self.mask_input_channels, kernel_size=2, stride=2)
757
+ self.conv2 = nn.Conv2d(self.mask_input_channels, config.mask_input_channels, kernel_size=2, stride=2)
758
+ self.conv3 = nn.Conv2d(config.mask_input_channels, config.hidden_size, kernel_size=1)
759
+ self.layer_norm1 = Sam2LayerNorm(
760
+ self.mask_input_channels, eps=config.layer_norm_eps, data_format="channels_first"
761
+ )
762
+ self.layer_norm2 = Sam2LayerNorm(
763
+ self.mask_input_channels * 4, eps=config.layer_norm_eps, data_format="channels_first"
764
+ )
765
+
766
+ def forward(self, masks):
767
+ hidden_states = self.conv1(masks)
768
+ hidden_states = self.layer_norm1(hidden_states)
769
+ hidden_states = self.activation(hidden_states)
770
+
771
+ hidden_states = self.conv2(hidden_states)
772
+ hidden_states = self.layer_norm2(hidden_states)
773
+ hidden_states = self.activation(hidden_states)
774
+ dense_embeddings = self.conv3(hidden_states)
775
+ return dense_embeddings
776
+
777
+
778
+ class Sam2PromptEncoder(nn.Module):
779
+ def __init__(self, config: Sam2PromptEncoderConfig):
780
+ super().__init__()
781
+ self.shared_embedding = Sam2PositionalEmbedding(config)
782
+ self.mask_embed = Sam2MaskEmbedding(config)
783
+ self.no_mask_embed = nn.Embedding(1, config.hidden_size)
784
+
785
+ self.image_embedding_size = (config.image_size // config.patch_size, config.image_size // config.patch_size)
786
+ self.mask_input_size = (4 * config.image_size // config.patch_size, 4 * config.image_size // config.patch_size)
787
+ self.input_image_size = config.image_size
788
+
789
+ self.point_embed = nn.Embedding(config.num_point_embeddings, config.hidden_size)
790
+ self.hidden_size = config.hidden_size
791
+ self.not_a_point_embed = nn.Embedding(1, config.hidden_size)
792
+
793
+ def _embed_points(self, points: torch.Tensor, labels: torch.Tensor, pad: bool) -> torch.Tensor:
794
+ """Embeds point prompts."""
795
+ points = points + 0.5 # Shift to center of pixel
796
+ if pad:
797
+ points = torch.nn.functional.pad(points, (0, 0, 0, 1), mode="constant", value=0)
798
+ labels = torch.nn.functional.pad(labels, (0, 1), mode="constant", value=-1)
799
+ input_shape = (self.input_image_size, self.input_image_size)
800
+ point_embedding = self.shared_embedding(points, input_shape)
801
+
802
+ # torch.where and expanding the labels tensor is required by the ONNX export
803
+ point_embedding = torch.where(labels[..., None] == -1, self.not_a_point_embed.weight, point_embedding)
804
+
805
+ # This is required for the ONNX export. The dtype, device need to be explicitly
806
+ # specified as otherwise torch.onnx.export interprets as double
807
+ point_embedding = torch.where(
808
+ labels[..., None] != -10,
809
+ point_embedding,
810
+ torch.zeros_like(point_embedding),
811
+ )
812
+
813
+ # Add point embeddings for labels >= 0
814
+ point_embedding = point_embedding + self.point_embed(labels.clamp(min=0)) * (labels >= 0).unsqueeze(-1)
815
+
816
+ return point_embedding
817
+
818
+ def _embed_boxes(self, boxes: torch.Tensor) -> torch.Tensor:
819
+ """Embeds box prompts."""
820
+ boxes = boxes + 0.5 # Shift to center of pixel
821
+ coords = boxes.view(*boxes.shape[:2], 2, 2)
822
+ # add padding point for consistency with the original implementation
823
+ coords = torch.nn.functional.pad(coords, (0, 0, 0, 1), mode="constant", value=0)
824
+ corner_embedding = self.shared_embedding(coords, (self.input_image_size, self.input_image_size))
825
+ corner_embedding[:, :, 0, :] += self.point_embed.weight[2]
826
+ corner_embedding[:, :, 1, :] += self.point_embed.weight[3]
827
+ corner_embedding[:, :, 2, :] = self.not_a_point_embed.weight.expand_as(corner_embedding[:, :, 2, :])
828
+ return corner_embedding
829
+
830
+ def forward(
831
+ self,
832
+ input_points: tuple[torch.Tensor, torch.Tensor] | None,
833
+ input_labels: torch.Tensor | None,
834
+ input_boxes: torch.Tensor | None,
835
+ input_masks: torch.Tensor | None,
836
+ ) -> tuple[torch.Tensor, torch.Tensor]:
837
+ """
838
+ Embeds different types of prompts, returning both sparse and dense embeddings.
839
+
840
+ Args:
841
+ points (`torch.Tensor`, *optional*):
842
+ point coordinates and labels to embed.
843
+ boxes (`torch.Tensor`, *optional*):
844
+ boxes to embed
845
+ masks (`torch.Tensor`, *optional*):
846
+ masks to embed
847
+ """
848
+ sparse_embeddings = None
849
+ batch_size = 1
850
+ if input_points is not None:
851
+ batch_size = input_points.shape[0]
852
+ if input_labels is None:
853
+ raise ValueError("If points are provided, labels must also be provided.")
854
+ point_embeddings = self._embed_points(input_points, input_labels, pad=(input_boxes is None))
855
+ sparse_embeddings = point_embeddings
856
+ if input_boxes is not None:
857
+ batch_size = input_boxes.shape[0]
858
+ box_embeddings = self._embed_boxes(input_boxes)
859
+ if sparse_embeddings is None:
860
+ sparse_embeddings = box_embeddings
861
+ else:
862
+ sparse_embeddings = torch.cat([sparse_embeddings, box_embeddings], dim=2)
863
+ if input_masks is not None:
864
+ dense_embeddings = self.mask_embed(input_masks)
865
+ else:
866
+ dense_embeddings = self.no_mask_embed.weight.reshape(1, -1, 1, 1).expand(
867
+ batch_size, -1, self.image_embedding_size[0], self.image_embedding_size[1]
868
+ )
869
+
870
+ return sparse_embeddings, dense_embeddings
871
+
872
+
873
+ class Sam2Attention(nn.Module):
874
+ """
875
+ SAM2's attention layer that allows for downscaling the size of the embedding after projection to queries, keys, and
876
+ values.
877
+ """
878
+
879
+ def __init__(self, config, downsample_rate=None):
880
+ super().__init__()
881
+ downsample_rate = config.attention_downsample_rate if downsample_rate is None else downsample_rate
882
+ self.config = config
883
+ self.hidden_size = config.hidden_size
884
+ self.internal_dim = config.hidden_size // downsample_rate
885
+ self.num_attention_heads = config.num_attention_heads
886
+ self.head_dim = self.internal_dim // config.num_attention_heads
887
+ self.scaling = self.head_dim**-0.5
888
+ self.is_causal = False
889
+
890
+ self.q_proj = nn.Linear(self.hidden_size, self.internal_dim)
891
+ self.k_proj = nn.Linear(self.hidden_size, self.internal_dim)
892
+ self.v_proj = nn.Linear(self.hidden_size, self.internal_dim)
893
+ self.o_proj = nn.Linear(self.internal_dim, self.hidden_size)
894
+
895
+ def forward(
896
+ self,
897
+ query: torch.Tensor,
898
+ key: torch.Tensor,
899
+ value: torch.Tensor,
900
+ attention_similarity: torch.Tensor | None = None,
901
+ **kwargs: Unpack[TransformersKwargs],
902
+ ) -> tuple[torch.Tensor, torch.Tensor]:
903
+ # Input projections
904
+ batch_size, point_batch_size = query.shape[:2]
905
+ new_shape = (batch_size * point_batch_size, -1, self.num_attention_heads, self.head_dim)
906
+
907
+ query = self.q_proj(query).view(*new_shape).transpose(1, 2)
908
+ key = self.k_proj(key).view(*new_shape).transpose(1, 2)
909
+ value = self.v_proj(value).view(*new_shape).transpose(1, 2)
910
+
911
+ attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
912
+ self.config._attn_implementation, eager_attention_forward
913
+ )
914
+
915
+ if is_flash_attention_requested(self.config) and attention_similarity is not None:
916
+ # Target guided masks are represented as float masks and are incompatible with Flash Attention
917
+ # Fallback to SDPA for this call only so the rest of the model can still benefit from FA
918
+ attention_interface = ALL_ATTENTION_FUNCTIONS["sdpa"]
919
+ logger.warning_once(
920
+ "Falling back to SDPA for target-guided attention because "
921
+ "Flash Attention does not support additive bias masks."
922
+ )
923
+
924
+ attn_output, attn_weights = attention_interface(
925
+ self,
926
+ query,
927
+ key,
928
+ value,
929
+ attention_mask=attention_similarity,
930
+ dropout=0.0,
931
+ scaling=self.scaling,
932
+ is_causal=self.is_causal,
933
+ **kwargs,
934
+ )
935
+
936
+ attn_output = attn_output.reshape(
937
+ batch_size, point_batch_size, -1, self.num_attention_heads * self.head_dim
938
+ ).contiguous()
939
+ attn_output = self.o_proj(attn_output)
940
+
941
+ return attn_output, attn_weights
942
+
943
+
944
+ class Sam2TwoWayAttentionBlock(GradientCheckpointingLayer):
945
+ def __init__(self, config: Sam2MaskDecoderConfig, skip_first_layer_pe: bool = False):
946
+ """
947
+ A transformer block with four layers:
948
+ (1) self-attention of sparse inputs (2) cross attention of sparse inputs -> dense inputs (3) mlp block on
949
+ sparse inputs (4) cross attention of dense inputs -> sparse inputs
950
+
951
+ Arguments:
952
+ config (`Sam2MaskDecoderConfig`):
953
+ The configuration file used to instantiate the block
954
+ attention_downsample_rate (*optionalk*, int, defaults to 2):
955
+ The downsample ratio of the block used to reduce the inner dim of the attention.
956
+ skip_first_layer_pe (*optional*, bool, defaults to `False`):
957
+ Whether or not to skip the addition of the query_point_embedding on the first layer.
958
+ """
959
+ super().__init__()
960
+ self.self_attn = Sam2Attention(config, downsample_rate=1)
961
+ self.layer_norm1 = nn.LayerNorm(config.hidden_size)
962
+
963
+ self.cross_attn_token_to_image = Sam2Attention(config)
964
+ self.layer_norm2 = nn.LayerNorm(config.hidden_size)
965
+
966
+ self.mlp = Sam2FeedForward(
967
+ config.hidden_size, config.mlp_dim, config.hidden_size, num_layers=config.num_hidden_layers
968
+ )
969
+ self.layer_norm3 = nn.LayerNorm(config.hidden_size)
970
+
971
+ self.layer_norm4 = nn.LayerNorm(config.hidden_size)
972
+ self.cross_attn_image_to_token = Sam2Attention(config)
973
+
974
+ self.skip_first_layer_pe = skip_first_layer_pe
975
+
976
+ def forward(
977
+ self,
978
+ queries: Tensor,
979
+ keys: Tensor,
980
+ query_point_embedding: Tensor,
981
+ key_point_embedding: Tensor,
982
+ attention_similarity: Tensor,
983
+ **kwargs: Unpack[TransformersKwargs],
984
+ ):
985
+ # Self attention block
986
+ if self.skip_first_layer_pe:
987
+ queries, _ = self.self_attn(query=queries, key=queries, value=queries)
988
+ else:
989
+ query = queries + query_point_embedding
990
+ attn_out, _ = self.self_attn(query=query, key=query, value=queries)
991
+ queries = queries + attn_out
992
+ queries = self.layer_norm1(queries)
993
+
994
+ # Cross attention block, tokens attending to image embedding
995
+ query = queries + query_point_embedding
996
+ key = keys + key_point_embedding
997
+
998
+ attn_out, _ = self.cross_attn_token_to_image(
999
+ query=query, key=key, value=keys, attention_similarity=attention_similarity
1000
+ )
1001
+ queries = queries + attn_out
1002
+
1003
+ queries = self.layer_norm2(queries)
1004
+
1005
+ # MLP block
1006
+ mlp_out = self.mlp(queries)
1007
+ queries = queries + mlp_out
1008
+ queries = self.layer_norm3(queries)
1009
+
1010
+ # Cross attention block, image embedding attending to tokens
1011
+ query = queries + query_point_embedding
1012
+ key = keys + key_point_embedding
1013
+
1014
+ attn_out, _ = self.cross_attn_image_to_token(query=key, key=query, value=queries)
1015
+ keys = keys + attn_out
1016
+
1017
+ keys = self.layer_norm4(keys)
1018
+ return queries, keys, attn_out
1019
+
1020
+
1021
+ class Sam2TwoWayTransformer(nn.Module):
1022
+ def __init__(self, config: Sam2MaskDecoderConfig):
1023
+ super().__init__()
1024
+ self.config = config
1025
+
1026
+ self.num_hidden_layers = config.num_hidden_layers
1027
+ self.layers = nn.ModuleList()
1028
+
1029
+ for i in range(self.num_hidden_layers):
1030
+ self.layers.append(Sam2TwoWayAttentionBlock(config, skip_first_layer_pe=(i == 0)))
1031
+
1032
+ self.final_attn_token_to_image = Sam2Attention(config)
1033
+ self.layer_norm_final_attn = nn.LayerNorm(config.hidden_size)
1034
+
1035
+ def forward(
1036
+ self,
1037
+ point_embeddings: Tensor,
1038
+ image_embeddings: Tensor,
1039
+ image_positional_embeddings: Tensor,
1040
+ attention_similarity: Tensor,
1041
+ target_embedding=None,
1042
+ **kwargs: Unpack[TransformersKwargs],
1043
+ ) -> tuple | BaseModelOutput:
1044
+ if image_embeddings is None:
1045
+ raise ValueError("You have to specify an image_embedding")
1046
+
1047
+ image_embeddings = image_embeddings.flatten(2).transpose(1, 2).unsqueeze(1)
1048
+ image_positional_embeddings = image_positional_embeddings.flatten(2).transpose(1, 2).unsqueeze(1)
1049
+
1050
+ # Prepare queries
1051
+ queries = point_embeddings
1052
+ keys = image_embeddings
1053
+
1054
+ # Apply transformer blocks and final layernorm
1055
+ for layer in self.layers:
1056
+ if target_embedding is not None:
1057
+ queries += target_embedding
1058
+
1059
+ queries, keys, _ = layer(
1060
+ queries=queries,
1061
+ keys=keys,
1062
+ query_point_embedding=point_embeddings,
1063
+ key_point_embedding=image_positional_embeddings,
1064
+ attention_similarity=attention_similarity,
1065
+ **kwargs,
1066
+ )
1067
+ # Apply the final attention layer from the points to the image
1068
+ query = queries + point_embeddings
1069
+ key = keys + image_positional_embeddings
1070
+
1071
+ attn_out, _ = self.final_attn_token_to_image(query=query, key=key, value=keys)
1072
+
1073
+ queries = queries + attn_out
1074
+ queries = self.layer_norm_final_attn(queries)
1075
+ return queries, keys
1076
+
1077
+
1078
+ class Sam2LayerNorm(nn.LayerNorm):
1079
+ r"""LayerNorm that supports two data formats: channels_last (default) or channels_first.
1080
+ The ordering of the dimensions in the inputs. channels_last corresponds to inputs with shape (batch_size, height,
1081
+ width, channels) while channels_first corresponds to inputs with shape (batch_size, channels, height, width).
1082
+ """
1083
+
1084
+ def __init__(self, normalized_shape, *, eps=1e-6, data_format="channels_last", **kwargs):
1085
+ super().__init__(normalized_shape, eps=eps, **kwargs)
1086
+ if data_format not in ["channels_last", "channels_first"]:
1087
+ raise NotImplementedError(f"Unsupported data format: {data_format}")
1088
+ self.data_format = data_format
1089
+
1090
+ def forward(self, features: torch.Tensor) -> torch.Tensor:
1091
+ """
1092
+ Args:
1093
+ features: Tensor of shape (batch_size, channels, height, width) OR (batch_size, height, width, channels)
1094
+ """
1095
+ if self.data_format == "channels_first":
1096
+ features = features.permute(0, 2, 3, 1)
1097
+ features = super().forward(features)
1098
+ features = features.permute(0, 3, 1, 2)
1099
+ else:
1100
+ features = super().forward(features)
1101
+ return features
1102
+
1103
+
1104
+ class Sam2MaskDecoder(nn.Module):
1105
+ def __init__(self, config: Sam2MaskDecoderConfig):
1106
+ super().__init__()
1107
+ self.config = config
1108
+ self.hidden_size = config.hidden_size
1109
+
1110
+ self.num_multimask_outputs = config.num_multimask_outputs
1111
+ self.num_mask_tokens = config.num_multimask_outputs + 1
1112
+
1113
+ self.iou_token = nn.Embedding(1, self.hidden_size)
1114
+ self.mask_tokens = nn.Embedding(self.num_mask_tokens, self.hidden_size)
1115
+
1116
+ self.transformer = Sam2TwoWayTransformer(config)
1117
+
1118
+ # should we create a new class for this?
1119
+ self.upscale_conv1 = nn.ConvTranspose2d(self.hidden_size, self.hidden_size // 4, kernel_size=2, stride=2)
1120
+ self.upscale_conv2 = nn.ConvTranspose2d(self.hidden_size // 4, self.hidden_size // 8, kernel_size=2, stride=2)
1121
+ self.upscale_layer_norm = Sam2LayerNorm(self.hidden_size // 4, data_format="channels_first")
1122
+ self.activation = nn.GELU()
1123
+
1124
+ mlps_list = []
1125
+ for _ in range(self.num_mask_tokens):
1126
+ mlps_list += [Sam2FeedForward(self.hidden_size, self.hidden_size, self.hidden_size // 8, 3)]
1127
+ self.output_hypernetworks_mlps = nn.ModuleList(mlps_list)
1128
+ self.iou_prediction_head = Sam2FeedForward(
1129
+ self.hidden_size,
1130
+ config.iou_head_hidden_dim,
1131
+ self.num_mask_tokens,
1132
+ config.iou_head_depth,
1133
+ sigmoid_output=True,
1134
+ )
1135
+
1136
+ self.conv_s0 = nn.Conv2d(config.hidden_size, config.hidden_size // 8, kernel_size=1, stride=1)
1137
+ self.conv_s1 = nn.Conv2d(config.hidden_size, config.hidden_size // 4, kernel_size=1, stride=1)
1138
+
1139
+ self.obj_score_token = nn.Embedding(1, self.hidden_size)
1140
+ self.pred_obj_score_head = Sam2FeedForward(self.hidden_size, self.hidden_size, 1, 3)
1141
+
1142
+ self.dynamic_multimask_via_stability = config.dynamic_multimask_via_stability
1143
+ self.dynamic_multimask_stability_delta = config.dynamic_multimask_stability_delta
1144
+ self.dynamic_multimask_stability_thresh = config.dynamic_multimask_stability_thresh
1145
+
1146
+ def forward(
1147
+ self,
1148
+ image_embeddings: torch.Tensor,
1149
+ image_positional_embeddings: torch.Tensor,
1150
+ sparse_prompt_embeddings: torch.Tensor,
1151
+ dense_prompt_embeddings: torch.Tensor,
1152
+ multimask_output: bool,
1153
+ high_resolution_features: list[torch.Tensor],
1154
+ attention_similarity: torch.Tensor | None = None,
1155
+ target_embedding: torch.Tensor | None = None,
1156
+ **kwargs: Unpack[TransformersKwargs],
1157
+ ) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
1158
+ """
1159
+ Predict masks given image and prompt embeddings.
1160
+
1161
+ Args:
1162
+ image_embeddings (`torch.Tensor`):
1163
+ The embeddings from the image encoder.
1164
+ image_positional_embeddings (`torch.Tensor`):
1165
+ Positional encoding with the shape of image_embeddings.
1166
+ sparse_prompt_embeddings (`torch.Tensor`):
1167
+ The embeddings of the points and boxes.
1168
+ dense_prompt_embeddings (`torch.Tensor`):
1169
+ The embeddings of the mask inputs.
1170
+ multimask_output (`bool`):
1171
+ Whether to return multiple masks or a single mask.
1172
+ high_resolution_features (`list[torch.Tensor]`, *optional*):
1173
+ The high-resolution features from the vision encoder.
1174
+ attention_similarity (`torch.Tensor`, *optional*):
1175
+ The attention similarity tensor.
1176
+ target_embedding (`torch.Tensor`, *optional*):
1177
+ The target embedding.
1178
+ """
1179
+ batch_size, num_channels, height, width = image_embeddings.shape
1180
+ point_batch_size = sparse_prompt_embeddings.shape[1]
1181
+ # Concatenate output tokens
1182
+ output_tokens = torch.cat(
1183
+ [
1184
+ self.obj_score_token.weight,
1185
+ self.iou_token.weight,
1186
+ self.mask_tokens.weight,
1187
+ ],
1188
+ dim=0,
1189
+ )
1190
+ output_tokens = output_tokens.repeat(batch_size, point_batch_size, 1, 1)
1191
+
1192
+ if sparse_prompt_embeddings.shape[0] != 0:
1193
+ tokens = torch.cat((output_tokens, sparse_prompt_embeddings), dim=2)
1194
+ else:
1195
+ tokens = output_tokens
1196
+ point_embeddings = tokens.to(self.iou_token.weight.dtype)
1197
+
1198
+ # Expand per-image data in batch direction to be per-mask
1199
+ image_embeddings = image_embeddings + dense_prompt_embeddings
1200
+ image_embeddings = image_embeddings.repeat_interleave(point_batch_size, dim=0)
1201
+ image_positional_embeddings = image_positional_embeddings.repeat_interleave(point_batch_size, 0)
1202
+ # Run the transformer
1203
+ point_embeddings, image_embeddings = self.transformer(
1204
+ point_embeddings=point_embeddings,
1205
+ image_embeddings=image_embeddings,
1206
+ image_positional_embeddings=image_positional_embeddings,
1207
+ attention_similarity=attention_similarity,
1208
+ target_embedding=target_embedding,
1209
+ **kwargs,
1210
+ )
1211
+ iou_token_out = point_embeddings[:, :, 1, :]
1212
+ mask_tokens_out = point_embeddings[:, :, 2 : (2 + self.num_mask_tokens), :]
1213
+
1214
+ # Upscale mask embeddings and predict masks using the mask tokens
1215
+ image_embeddings = image_embeddings.transpose(2, 3).view(
1216
+ batch_size * point_batch_size, num_channels, height, width
1217
+ )
1218
+
1219
+ feat_s0, feat_s1 = high_resolution_features
1220
+ feat_s0 = feat_s0.repeat_interleave(point_batch_size, dim=0)
1221
+ feat_s1 = feat_s1.repeat_interleave(point_batch_size, dim=0)
1222
+ upscaled_embedding = self.upscale_conv1(image_embeddings) + feat_s1
1223
+ upscaled_embedding = self.activation(self.upscale_layer_norm(upscaled_embedding))
1224
+ upscaled_embedding = self.activation(self.upscale_conv2(upscaled_embedding) + feat_s0)
1225
+
1226
+ hyper_in_list: list[torch.Tensor] = []
1227
+ for i in range(self.num_mask_tokens):
1228
+ current_mlp = self.output_hypernetworks_mlps[i]
1229
+ hyper_in_list += [current_mlp(mask_tokens_out[:, :, i, :])]
1230
+ hyper_in = torch.stack(hyper_in_list, dim=2)
1231
+
1232
+ _, num_channels, height, width = upscaled_embedding.shape
1233
+ upscaled_embedding = upscaled_embedding.view(batch_size, point_batch_size, num_channels, height * width)
1234
+ masks = (hyper_in @ upscaled_embedding).view(batch_size, point_batch_size, -1, height, width)
1235
+
1236
+ # Generate mask quality predictions
1237
+ iou_pred = self.iou_prediction_head(iou_token_out)
1238
+ object_score_logits = self.pred_obj_score_head(point_embeddings[:, :, 0, :])
1239
+
1240
+ # Select the correct mask or masks for output
1241
+ if multimask_output:
1242
+ mask_slice = slice(1, None)
1243
+ masks = masks[:, :, mask_slice, :, :]
1244
+ iou_pred = iou_pred[:, :, mask_slice]
1245
+ elif self.dynamic_multimask_via_stability and not self.training:
1246
+ mask_slice = slice(0, 1)
1247
+ masks, iou_pred = self._dynamic_multimask_via_stability(masks, iou_pred)
1248
+ else:
1249
+ mask_slice = slice(0, 1)
1250
+ masks = masks[:, :, mask_slice, :, :]
1251
+ iou_pred = iou_pred[:, :, mask_slice]
1252
+
1253
+ sam_tokens_out = mask_tokens_out[:, :, mask_slice] # [b, 3, c] shape
1254
+
1255
+ return masks, iou_pred, sam_tokens_out, object_score_logits
1256
+
1257
+ def _get_stability_scores(self, mask_logits):
1258
+ """
1259
+ Compute stability scores of the mask logits based on the IoU between upper and
1260
+ lower thresholds.
1261
+ """
1262
+ mask_logits = mask_logits.flatten(-2)
1263
+ stability_delta = self.dynamic_multimask_stability_delta
1264
+ area_i = torch.sum(mask_logits > stability_delta, dim=-1).float()
1265
+ area_u = torch.sum(mask_logits > -stability_delta, dim=-1).float()
1266
+ stability_scores = torch.where(area_u > 0, area_i / area_u, 1.0)
1267
+ return stability_scores
1268
+
1269
+ def _dynamic_multimask_via_stability(self, all_mask_logits, all_iou_scores):
1270
+ """
1271
+ When outputting a single mask, if the stability score from the current single-mask
1272
+ output (based on output token 0) falls below a threshold, we instead select from
1273
+ multi-mask outputs (based on output token 1~3) the mask with the highest predicted
1274
+ IoU score. This is intended to ensure a valid mask for both clicking and tracking.
1275
+ """
1276
+ # The best mask from multimask output tokens (1~3)
1277
+ multimask_logits = all_mask_logits[:, :, 1:, :, :]
1278
+ multimask_iou_scores = all_iou_scores[:, :, 1:]
1279
+ best_scores_inds = torch.argmax(multimask_iou_scores, dim=-1) # [B, P]
1280
+ best_scores_inds_expanded = best_scores_inds.unsqueeze(-1).unsqueeze(-1).unsqueeze(-1)
1281
+ best_scores_inds_expanded = best_scores_inds_expanded.expand(
1282
+ -1, -1, 1, multimask_logits.size(-2), multimask_logits.size(-1)
1283
+ )
1284
+ best_multimask_logits = torch.gather(multimask_logits, 2, best_scores_inds_expanded) # [B, P, 1, H, W]
1285
+ best_multimask_iou_scores = torch.gather(multimask_iou_scores, 2, best_scores_inds.unsqueeze(-1)) # [B, P, 1]
1286
+
1287
+ # The mask from singlemask output token 0 and its stability score
1288
+ singlemask_logits = all_mask_logits[:, :, 0:1, :, :]
1289
+ singlemask_iou_scores = all_iou_scores[:, :, 0:1]
1290
+ stability_scores = self._get_stability_scores(singlemask_logits)
1291
+ is_stable = stability_scores >= self.dynamic_multimask_stability_thresh
1292
+
1293
+ # Dynamically fall back to best multimask output upon low stability scores.
1294
+ mask_logits_out = torch.where(
1295
+ is_stable[..., None, None].expand_as(singlemask_logits),
1296
+ singlemask_logits,
1297
+ best_multimask_logits,
1298
+ )
1299
+ iou_scores_out = torch.where(
1300
+ is_stable.expand_as(singlemask_iou_scores),
1301
+ singlemask_iou_scores,
1302
+ best_multimask_iou_scores,
1303
+ )
1304
+ return mask_logits_out, iou_scores_out
1305
+
1306
+
1307
+ @auto_docstring(
1308
+ custom_intro="""
1309
+ Segment Anything Model 2 (SAM 2) for generating segmentation masks, given an input image and
1310
+ input points and labels, boxes, or masks.
1311
+ """
1312
+ )
1313
+ class Sam2Model(Sam2PreTrainedModel):
1314
+ input_modalities = ("image", "text")
1315
+ _can_record_outputs = {"mask_decoder_attentions": OutputRecorder(Sam2TwoWayAttentionBlock, index=2)}
1316
+ _tied_weights_keys = {}
1317
+
1318
+ def __init__(self, config: Sam2Config):
1319
+ super().__init__(config)
1320
+ self.shared_image_embedding = Sam2PositionalEmbedding(config.prompt_encoder_config)
1321
+ self.vision_encoder = AutoModel.from_config(config.vision_config)
1322
+ self.prompt_encoder = Sam2PromptEncoder(config.prompt_encoder_config)
1323
+ # The module using it is not a PreTrainedModel subclass so we need this
1324
+ config.mask_decoder_config._attn_implementation = config._attn_implementation
1325
+ self.mask_decoder = Sam2MaskDecoder(config.mask_decoder_config)
1326
+
1327
+ self.num_feature_levels = config.vision_config.num_feature_levels
1328
+ self.backbone_feature_sizes = config.vision_config.backbone_feature_sizes
1329
+ # a single token to indicate no memory embedding from previous frames
1330
+ self.hidden_dim = config.vision_config.fpn_hidden_size
1331
+ self.no_memory_embedding = torch.nn.Parameter(torch.zeros(1, 1, self.hidden_dim))
1332
+
1333
+ self.post_init()
1334
+
1335
+ def get_input_embeddings(self):
1336
+ return self.vision_encoder.get_input_embeddings()
1337
+
1338
+ def get_image_wide_positional_embeddings(self) -> torch.Tensor:
1339
+ size = self.prompt_encoder.image_embedding_size
1340
+ target_device = self.shared_image_embedding.positional_embedding.device
1341
+ target_dtype = self.shared_image_embedding.positional_embedding.dtype
1342
+ grid = torch.ones(size, device=target_device, dtype=target_dtype)
1343
+ y_embed = grid.cumsum(dim=0) - 0.5
1344
+ x_embed = grid.cumsum(dim=1) - 0.5
1345
+ y_embed = y_embed / size[0]
1346
+ x_embed = x_embed / size[1]
1347
+
1348
+ positional_embedding = self.shared_image_embedding(torch.stack([x_embed, y_embed], dim=-1))
1349
+ return positional_embedding.permute(2, 0, 1).unsqueeze(0) # channel x height x width
1350
+
1351
+ @torch.no_grad()
1352
+ def get_image_embeddings(
1353
+ self,
1354
+ pixel_values: torch.FloatTensor,
1355
+ **kwargs: Unpack[TransformersKwargs],
1356
+ ) -> list[torch.Tensor]:
1357
+ r"""
1358
+ Returns the image embeddings by passing the pixel values through the vision encoder.
1359
+
1360
+ Args:
1361
+ pixel_values (`torch.FloatTensor` of shape `(batch_size, num_channels, height, width)`):
1362
+ Input pixel values
1363
+ """
1364
+ batch_size = pixel_values.shape[0]
1365
+ image_outputs = self.get_image_features(pixel_values, return_dict=True, **kwargs)
1366
+ feature_maps = image_outputs.fpn_hidden_states
1367
+
1368
+ # add no memory embedding to the last feature map
1369
+ feature_maps[-1] = feature_maps[-1] + self.no_memory_embedding
1370
+
1371
+ # reshape feature maps to the same shape as the backbone feature sizes
1372
+ image_embeddings = [
1373
+ feat.permute(1, 2, 0).view(batch_size, -1, *feat_size)
1374
+ for feat, feat_size in zip(feature_maps, self.backbone_feature_sizes)
1375
+ ]
1376
+
1377
+ return image_embeddings
1378
+
1379
+ @torch.no_grad()
1380
+ def get_prompt_embeddings(
1381
+ self,
1382
+ input_points: torch.FloatTensor | None = None,
1383
+ input_labels: torch.LongTensor | None = None,
1384
+ input_boxes: torch.FloatTensor | None = None,
1385
+ input_masks: torch.LongTensor | None = None,
1386
+ ):
1387
+ r"""
1388
+ Returns the prompt embeddings by passing the input points, labels, boxes and masks through the prompt encoder.
1389
+
1390
+ Args:
1391
+ input_points (`torch.FloatTensor` of shape `(batch_size, point_batch_size, num_points_per_image, 2)`):
1392
+ Optional input points for the prompt encoder. The padding of the point is automatically done by the
1393
+ processor. `point_batch_size` refers to the number of masks that we want the model to predict per
1394
+ point. The model will output `point_batch_size` times 3 masks in total.
1395
+ input_labels (`torch.LongTensor` of shape `(batch_size, point_batch_size, num_points_per_image)`):
1396
+ Optional input labels for the prompt encoder. The padding of the labels is automatically done by the
1397
+ processor, or can be fed by the user.
1398
+ input_boxes (`torch.FloatTensor` of shape `(batch_size, num_boxes_per_image, 4)`):
1399
+ Optional input boxes for the prompt encoder. The padding of the boxes is automatically done by the
1400
+ processor. users can also pass manually the input boxes.
1401
+ input_masks (`torch.LongTensor` of shape `(batch_size, image_size, image_size)`):
1402
+ Optional input masks for the prompt encoder.
1403
+ """
1404
+ prompt_output = self.prompt_encoder(
1405
+ input_points=input_points,
1406
+ input_labels=input_labels,
1407
+ input_boxes=input_boxes,
1408
+ input_masks=input_masks,
1409
+ )
1410
+ return prompt_output
1411
+
1412
+ @merge_with_config_defaults
1413
+ @capture_outputs
1414
+ @auto_docstring
1415
+ def forward(
1416
+ self,
1417
+ pixel_values: torch.FloatTensor | None = None,
1418
+ input_points: torch.FloatTensor | None = None,
1419
+ input_labels: torch.LongTensor | None = None,
1420
+ input_boxes: torch.FloatTensor | None = None,
1421
+ input_masks: torch.LongTensor | None = None,
1422
+ image_embeddings: torch.FloatTensor | None = None,
1423
+ multimask_output: bool = True,
1424
+ attention_similarity: torch.FloatTensor | None = None,
1425
+ target_embedding: torch.FloatTensor | None = None,
1426
+ **kwargs: Unpack[TransformersKwargs],
1427
+ ) -> Sam2ImageSegmentationOutput:
1428
+ r"""
1429
+ input_points (`torch.FloatTensor` of shape `(batch_size, num_points, 2)`):
1430
+ Input 2D spatial points, this is used by the prompt encoder to encode the prompt. Generally yields to much
1431
+ better results. The points can be obtained by passing a list of list of list to the processor that will
1432
+ create corresponding `torch` tensors of dimension 4. The first dimension is the image batch size, the
1433
+ second dimension is the point batch size (i.e. how many segmentation masks do we want the model to predict
1434
+ per input point), the third dimension is the number of points per segmentation mask (it is possible to pass
1435
+ multiple points for a single mask), and the last dimension is the x (vertical) and y (horizontal)
1436
+ coordinates of the point. If a different number of points is passed either for each image, or for each
1437
+ mask, the processor will create "PAD" points that will correspond to the (0, 0) coordinate, and the
1438
+ computation of the embedding will be skipped for these points using the labels.
1439
+ input_labels (`torch.LongTensor` of shape `(batch_size, point_batch_size, num_points)`):
1440
+ Input labels for the points, this is used by the prompt encoder to encode the prompt. According to the
1441
+ official implementation, there are 3 types of labels
1442
+
1443
+ - `1`: the point is a point that contains the object of interest
1444
+ - `0`: the point is a point that does not contain the object of interest
1445
+ - `-1`: the point corresponds to the background
1446
+
1447
+ We added the label:
1448
+
1449
+ - `-10`: the point is a padding point, thus should be ignored by the prompt encoder
1450
+
1451
+ The padding labels should be automatically done by the processor.
1452
+ input_boxes (`torch.FloatTensor` of shape `(batch_size, num_boxes, 4)`):
1453
+ Input boxes for the points, this is used by the prompt encoder to encode the prompt. Generally yields to
1454
+ much better generated masks. The boxes can be obtained by passing a list of list of list to the processor,
1455
+ that will generate a `torch` tensor, with each dimension corresponding respectively to the image batch
1456
+ size, the number of boxes per image and the coordinates of the top left and bottom right point of the box.
1457
+ In the order (`x1`, `y1`, `x2`, `y2`):
1458
+
1459
+ - `x1`: the x coordinate of the top left point of the input box
1460
+ - `y1`: the y coordinate of the top left point of the input box
1461
+ - `x2`: the x coordinate of the bottom right point of the input box
1462
+ - `y2`: the y coordinate of the bottom right point of the input box
1463
+ input_masks (`torch.FloatTensor` of shape `(batch_size, image_size, image_size)`):
1464
+ SAM model also accepts segmentation masks as input. The mask will be embedded by the prompt encoder to
1465
+ generate a corresponding embedding, that will be fed later on to the mask decoder. These masks needs to be
1466
+ manually fed by the user, and they need to be of shape (`batch_size`, `image_size`, `image_size`).
1467
+ image_embeddings (`torch.FloatTensor` of shape `(batch_size, output_channels, window_size, window_size)`):
1468
+ Image embeddings, this is used by the mask decoder to generate masks and iou scores. For more memory
1469
+ efficient computation, users can first retrieve the image embeddings using the `get_image_embeddings`
1470
+ method, and then feed them to the `forward` method instead of feeding the `pixel_values`.
1471
+ multimask_output (`bool`, *optional*):
1472
+ In the original implementation and paper, the model always outputs 3 masks per image (or per point / per
1473
+ bounding box if relevant). However, it is possible to just output a single mask, that corresponds to the
1474
+ "best" mask, by specifying `multimask_output=False`.
1475
+ attention_similarity (`torch.FloatTensor`, *optional*):
1476
+ Attention similarity tensor, to be provided to the mask decoder for target-guided attention in case the
1477
+ model is used for personalization as introduced in [PerSAM](https://huggingface.co/papers/2305.03048).
1478
+ target_embedding (`torch.FloatTensor`, *optional*):
1479
+ Embedding of the target concept, to be provided to the mask decoder for target-semantic prompting in case
1480
+ the model is used for personalization as introduced in [PerSAM](https://huggingface.co/papers/2305.03048).
1481
+
1482
+ Example:
1483
+
1484
+ ```python
1485
+ >>> from PIL import Image
1486
+ >>> import httpx
1487
+ >>> from io import BytesIO
1488
+ >>> from transformers import AutoModel, AutoProcessor
1489
+
1490
+ >>> model = AutoModel.from_pretrained("danelcsb/sam2.1_hiera_tiny")
1491
+ >>> processor = AutoProcessor.from_pretrained("danelcsb/sam2.1_hiera_tiny")
1492
+
1493
+ >>> url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/model_doc/sam-car.png"
1494
+ >>> with httpx.stream("GET", url) as response:
1495
+ ... raw_image = Image.open(BytesIO(response.read())).convert("RGB")
1496
+ >>> input_points = [[[400, 650]]] # 2D location of a window on the car
1497
+ >>> inputs = processor(images=raw_image, input_points=input_points, return_tensors="pt")
1498
+
1499
+ >>> # Get segmentation mask
1500
+ >>> outputs = model(**inputs)
1501
+
1502
+ >>> # Postprocess masks
1503
+ >>> masks = processor.post_process_masks(
1504
+ ... outputs.pred_masks, inputs["original_sizes"]
1505
+ ... )
1506
+ ```
1507
+ """
1508
+ if not ((pixel_values is None) ^ (image_embeddings is None)):
1509
+ raise ValueError("Exactly one of pixel_values or image_embeddings must be provided.")
1510
+ if input_points is not None and input_boxes is not None:
1511
+ if input_points.shape[1] != input_boxes.shape[1]:
1512
+ raise ValueError(
1513
+ f"You should provide as many bounding boxes as input points per box. Got {input_points.shape[1]} and {input_boxes.shape[1]}."
1514
+ )
1515
+
1516
+ image_positional_embeddings = self.get_image_wide_positional_embeddings()
1517
+ # repeat with batch size
1518
+ batch_size = pixel_values.shape[0] if pixel_values is not None else image_embeddings[-1].shape[0]
1519
+ image_positional_embeddings = image_positional_embeddings.repeat(batch_size, 1, 1, 1)
1520
+
1521
+ vision_attentions = None
1522
+ vision_hidden_states = None
1523
+
1524
+ if pixel_values is not None:
1525
+ image_outputs: Sam2VisionEncoderOutput = self.get_image_features(pixel_values, return_dict=True, **kwargs)
1526
+ feature_maps = image_outputs.fpn_hidden_states
1527
+ vision_hidden_states = image_outputs.hidden_states
1528
+ vision_attentions = image_outputs.attentions
1529
+
1530
+ # add no memory embedding to the last feature map
1531
+ feature_maps[-1] = feature_maps[-1] + self.no_memory_embedding
1532
+
1533
+ # reshape feature maps to the same shape as the backbone feature sizes
1534
+ image_embeddings = [
1535
+ feat.permute(1, 2, 0).view(batch_size, -1, *feat_size)
1536
+ for feat, feat_size in zip(feature_maps, self.backbone_feature_sizes)
1537
+ ]
1538
+
1539
+ if input_points is not None and input_labels is None:
1540
+ input_labels = torch.ones_like(input_points[:, :, :, 0], dtype=torch.int, device=input_points.device)
1541
+
1542
+ if input_points is None and input_boxes is None:
1543
+ # If no points are provide, pad with an empty point (with label -1)
1544
+ input_points = torch.zeros(
1545
+ batch_size, 1, 1, 2, dtype=image_embeddings[-1].dtype, device=image_embeddings[-1].device
1546
+ )
1547
+ input_labels = -torch.ones(batch_size, 1, 1, dtype=torch.int32, device=image_embeddings[-1].device)
1548
+
1549
+ if input_masks is not None:
1550
+ # If mask_inputs is provided, downsize it into low-res mask input if needed
1551
+ # and feed it as a dense mask prompt into the SAM mask encoder
1552
+ if input_masks.shape[-2:] != self.prompt_encoder.mask_input_size:
1553
+ input_masks = F.interpolate(
1554
+ input_masks.float(),
1555
+ size=self.prompt_encoder.mask_input_size,
1556
+ align_corners=False,
1557
+ mode="bilinear",
1558
+ antialias=True, # use antialias for downsampling
1559
+ ).to(input_masks.dtype)
1560
+
1561
+ sparse_embeddings, dense_embeddings = self.prompt_encoder(
1562
+ input_points=input_points,
1563
+ input_labels=input_labels,
1564
+ input_boxes=input_boxes,
1565
+ input_masks=input_masks,
1566
+ )
1567
+ low_res_multimasks, iou_scores, _, object_score_logits = self.mask_decoder(
1568
+ image_embeddings=image_embeddings[-1],
1569
+ image_positional_embeddings=image_positional_embeddings,
1570
+ sparse_prompt_embeddings=sparse_embeddings,
1571
+ dense_prompt_embeddings=dense_embeddings,
1572
+ multimask_output=multimask_output,
1573
+ high_resolution_features=image_embeddings[:-1],
1574
+ attention_similarity=attention_similarity,
1575
+ target_embedding=target_embedding,
1576
+ **kwargs,
1577
+ )
1578
+
1579
+ return Sam2ImageSegmentationOutput(
1580
+ iou_scores=iou_scores,
1581
+ pred_masks=low_res_multimasks,
1582
+ object_score_logits=object_score_logits,
1583
+ image_embeddings=image_embeddings,
1584
+ vision_hidden_states=vision_hidden_states,
1585
+ vision_attentions=vision_attentions,
1586
+ )
1587
+
1588
+ @can_return_tuple
1589
+ @auto_docstring
1590
+ def get_image_features(
1591
+ self,
1592
+ pixel_values: torch.FloatTensor,
1593
+ **kwargs: Unpack[TransformersKwargs],
1594
+ ) -> tuple | Sam2VisionEncoderOutput:
1595
+ r"""
1596
+ pixel_values (`torch.FloatTensor`):
1597
+ Input pixel values of shape `(batch_size, num_channels, height, width)`.
1598
+ """
1599
+ vision_outputs: Sam2VisionEncoderOutput = self.vision_encoder(pixel_values, return_dict=True, **kwargs)
1600
+
1601
+ feature_maps = vision_outputs.fpn_hidden_states
1602
+ feature_maps_position_embeddings = vision_outputs.fpn_position_encoding
1603
+
1604
+ # precompute projected level 0 and level 1 features in SAM decoder
1605
+ # to avoid running it again on every SAM click
1606
+ feature_maps = list(feature_maps)
1607
+ feature_maps[0] = self.mask_decoder.conv_s0(feature_maps[0])
1608
+ feature_maps[1] = self.mask_decoder.conv_s1(feature_maps[1])
1609
+
1610
+ # flatten NxCxHxW to HWxNxC
1611
+ feature_maps = [feature_map.flatten(2).permute(2, 0, 1) for feature_map in feature_maps]
1612
+ feature_maps_position_embeddings = [
1613
+ feature_maps_position_embeddings.flatten(2).permute(2, 0, 1)
1614
+ for feature_maps_position_embeddings in feature_maps_position_embeddings
1615
+ ]
1616
+ vision_outputs.fpn_hidden_states = feature_maps
1617
+ vision_outputs.fpn_position_encoding = feature_maps_position_embeddings
1618
+
1619
+ return vision_outputs
1620
+
1621
+
1622
+ __all__ = ["Sam2Model", "Sam2VisionModel", "Sam2PreTrainedModel", "Sam2HieraDetModel"]