@@ -52,6 +52,7 @@ def call(
5252 training : Optional [bool ] = None ,
5353 return_attention_scores : bool = False ,
5454 use_causal_mask : bool = False ,
55+ ** kwargs ,
5556 ):
5657 """use query and key generating an attention multiplier for value, multi_heads to repeat it
5758
@@ -110,12 +111,31 @@ def get_config(self):
110111 return dict (list (base_config .items ()) + list (config .items ()))
111112
112113 def compute_output_shape (self , input_shape ):
113- if isinstance (input_shape , (list , tuple )) and len (input_shape ) == 3 :
114- q_shape = input_shape [0 ]
115- else :
116- raise ValueError ("Expected input_shape to be a list or tuple of three elements (q, k, v)" )
114+ if isinstance (input_shape , tuple ) and len (input_shape ) == 3 :
115+ batch_size , seq_len , _ = input_shape
116+ return (batch_size , seq_len , self .hidden_size )
117+
118+ elif isinstance (input_shape , (list , tuple )) and len (input_shape ) == 3 :
119+ q_shape , k_shape , v_shape = input_shape
120+
121+ # Validate that all shapes are tuples with 3 dimensions
122+ if not all (isinstance (shape , tuple ) and len (shape ) == 3 for shape in [q_shape , k_shape , v_shape ]):
123+ raise ValueError (
124+ "Each input shape must be a tuple of length 3 (batch_size, seq_len, features). "
125+ f"Got shapes: q={ q_shape } , k={ k_shape } , v={ v_shape } "
126+ )
127+
128+ # Output shape is based on query sequence length
129+ batch_size , seq_q_len , _ = q_shape
130+ return (batch_size , seq_q_len , self .hidden_size )
117131
118- return (q_shape [0 ], q_shape [1 ], self .hidden_size )
132+ else :
133+ raise ValueError (
134+ "Expected input_shape to be either:\n "
135+ "1. A single tuple (batch_size, seq_len, features) for self-attention, or\n "
136+ "2. A list/tuple of 3 shapes [(q_shape), (k_shape), (v_shape)] for cross-attention.\n "
137+ f"Got: { input_shape } "
138+ )
119139
120140
121141class SelfAttention (tf .keras .layers .Layer ):
0 commit comments