@@ -72,6 +72,14 @@ pub struct CommonExt {
7272 #[ builder( default , setter( strip_option) ) ]
7373 #[ allow( unused) ] // Not used
7474 pub guided_whitespace_pattern : Option < String > ,
75+
76+ /// Whether to skip special tokens in the decoded output.
77+ /// When true, special tokens (like EOS, BOS, PAD) are removed from the output text.
78+ /// When false, special tokens are included in the output text.
79+ /// Defaults to false if not specified.
80+ #[ serde( default , skip_serializing_if = "Option::is_none" ) ]
81+ #[ builder( default , setter( strip_option) ) ]
82+ pub skip_special_tokens : Option < bool > ,
7583}
7684
7785impl CommonExt {
@@ -99,6 +107,9 @@ pub trait CommonExtProvider {
99107 fn get_min_p ( & self ) -> Option < f32 > ;
100108 fn get_repetition_penalty ( & self ) -> Option < f32 > ;
101109 fn get_include_stop_str_in_output ( & self ) -> Option < bool > ;
110+
111+ /// Output Options
112+ fn get_skip_special_tokens ( & self ) -> Option < bool > ;
102113}
103114
104115#[ cfg( test) ]
@@ -120,6 +131,7 @@ mod tests {
120131 assert_eq ! ( common_ext. guided_choice, None ) ;
121132 assert_eq ! ( common_ext. guided_decoding_backend, None ) ;
122133 assert_eq ! ( common_ext. include_stop_str_in_output, None ) ;
134+ assert_eq ! ( common_ext. skip_special_tokens, None ) ;
123135 }
124136
125137 #[ test]
@@ -135,6 +147,7 @@ mod tests {
135147 . guided_grammar ( "grammar" . to_string ( ) )
136148 . guided_choice ( vec ! [ "choice1" . to_string( ) , "choice2" . to_string( ) ] )
137149 . guided_decoding_backend ( "backend" . to_string ( ) )
150+ . skip_special_tokens ( false )
138151 . build ( )
139152 . unwrap ( ) ;
140153
@@ -157,6 +170,7 @@ mod tests {
157170 common_ext. guided_decoding_backend,
158171 Some ( "backend" . to_string( ) )
159172 ) ;
173+ assert_eq ! ( common_ext. skip_special_tokens, Some ( false ) ) ;
160174 }
161175
162176 #[ test]
@@ -190,6 +204,7 @@ mod tests {
190204 guided_choice : None ,
191205 guided_decoding_backend : None ,
192206 guided_whitespace_pattern : None ,
207+ skip_special_tokens : None ,
193208 } ;
194209 assert ! ( common_ext. validate( ) . is_ok( ) ) ;
195210 }
@@ -219,4 +234,52 @@ mod tests {
219234 assert_eq ! ( common_ext. include_stop_str_in_output, None ) ;
220235 assert ! ( common_ext. validate( ) . is_ok( ) ) ;
221236 }
237+
238+ #[ test]
239+ fn test_skip_special_tokens_field ( ) {
240+ // Test that skip_special_tokens can be set and retrieved
241+ let common_ext = CommonExt :: builder ( )
242+ . skip_special_tokens ( true )
243+ . build ( )
244+ . unwrap ( ) ;
245+
246+ assert_eq ! ( common_ext. skip_special_tokens, Some ( true ) ) ;
247+
248+ let common_ext = CommonExt :: builder ( )
249+ . skip_special_tokens ( false )
250+ . build ( )
251+ . unwrap ( ) ;
252+
253+ assert_eq ! ( common_ext. skip_special_tokens, Some ( false ) ) ;
254+ }
255+
256+ #[ test]
257+ fn test_skip_special_tokens_serialization ( ) {
258+ // Test that skip_special_tokens can be serialized and deserialized
259+ let common_ext = CommonExt :: builder ( )
260+ . skip_special_tokens ( true )
261+ . build ( )
262+ . unwrap ( ) ;
263+
264+ let json = serde_json:: to_string ( & common_ext) . unwrap ( ) ;
265+ let deserialized: CommonExt = serde_json:: from_str ( & json) . unwrap ( ) ;
266+
267+ assert_eq ! ( deserialized. skip_special_tokens, Some ( true ) ) ;
268+
269+ // Test with false value
270+ let common_ext = CommonExt :: builder ( )
271+ . skip_special_tokens ( false )
272+ . build ( )
273+ . unwrap ( ) ;
274+
275+ let json = serde_json:: to_string ( & common_ext) . unwrap ( ) ;
276+ let deserialized: CommonExt = serde_json:: from_str ( & json) . unwrap ( ) ;
277+
278+ assert_eq ! ( deserialized. skip_special_tokens, Some ( false ) ) ;
279+
280+ // Test that None is not serialized (skip_serializing_if = "Option::is_none")
281+ let common_ext = CommonExt :: builder ( ) . build ( ) . unwrap ( ) ;
282+ let json = serde_json:: to_string ( & common_ext) . unwrap ( ) ;
283+ assert ! ( !json. contains( "skip_special_tokens" ) ) ;
284+ }
222285}
0 commit comments