@@ -189,6 +189,10 @@ private static async Task<string> SendChatRequest(
189
189
190
190
OpenAIResponse ? chatResponse = JsonSerializer . Deserialize < OpenAIResponse > ( jsonResultString ) ;
191
191
string reply = chatResponse ! . choices [ 0 ] . message . content ;
192
+ if ( settings . ReasonStripRequired )
193
+ {
194
+ reply = ChatReplyParser . StripReasoning ( reply ) ;
195
+ }
192
196
193
197
return reply . Trim ( ) ;
194
198
}
@@ -276,3 +280,57 @@ public class OpenAIChoice
276
280
{
277
281
public OpenAIMessage message { get ; set ; }
278
282
}
283
+
284
+ public static class ChatReplyParser
285
+ {
286
+ // Target tag names to remove (lowercase)
287
+ private static readonly string [ ] Tags = [ "think" , "reason" , "reasoning" , "thought" ] ;
288
+
289
+ // open/close tag strings from tag names
290
+ private static readonly string [ ] OpenTags ;
291
+ private static readonly string [ ] CloseTags ;
292
+
293
+ static ChatReplyParser ( )
294
+ {
295
+ OpenTags = new string [ Tags . Length ] ;
296
+ CloseTags = new string [ Tags . Length ] ;
297
+ for ( int i = 0 ; i < Tags . Length ; i ++ )
298
+ {
299
+ OpenTags [ i ] = $ "<{ Tags [ i ] } >"; // e.g. "<think>"
300
+ CloseTags [ i ] = $ "</{ Tags [ i ] } >"; // e.g. "</think>"
301
+ }
302
+ }
303
+
304
+ /// <summary>
305
+ /// Removes a leading reasoning tag if present and returns only the generated message portion.
306
+ /// </summary>
307
+ public static string StripReasoning ( string input )
308
+ {
309
+ // Return immediately if it doesn't start with a tag
310
+ if ( string . IsNullOrEmpty ( input ) || input [ 0 ] != '<' )
311
+ return input ;
312
+
313
+ var span = input . AsSpan ( ) ;
314
+
315
+ for ( int i = 0 ; i < OpenTags . Length ; i ++ )
316
+ {
317
+ if ( span . StartsWith ( OpenTags [ i ] , StringComparison . OrdinalIgnoreCase ) )
318
+ {
319
+ int endIdx = span . IndexOf ( CloseTags [ i ] , StringComparison . OrdinalIgnoreCase ) ;
320
+ if ( endIdx >= 0 )
321
+ {
322
+ int next = endIdx + CloseTags [ i ] . Length ;
323
+ // Skip over any consecutive line breaks and whitespace
324
+ while ( next < span . Length && char . IsWhiteSpace ( span [ next ] ) )
325
+ {
326
+ next ++ ;
327
+ }
328
+ return span . Slice ( next ) . ToString ( ) ;
329
+ }
330
+ }
331
+ }
332
+
333
+ // Return original string if no tag matched
334
+ return input ;
335
+ }
336
+ }
0 commit comments