17
17
from typing import Optional , Union
18
18
19
19
from fastdeploy .entrypoints .openai .protocol import (ChatCompletionRequest ,
20
- DeltaMessage )
20
+ DeltaMessage )
21
21
from fastdeploy .reasoning import ReasoningParser , ReasoningParserManager
22
22
23
23
@@ -67,79 +67,95 @@ def extract_reasoning_content_streaming(
67
67
- 'abc' goes to reasoning_content
68
68
- 'xyz' goes to content
69
69
"""
70
- # Skip single special tokens
71
70
if len (delta_token_ids ) == 1 and (delta_token_ids [0 ] in [
72
71
self .think_start_token_id , self .think_end_token_id
73
72
]):
74
73
return "" , ""
75
74
76
- if self .think_start_token_id in previous_token_ids :
77
- if self .think_end_token_id in delta_token_ids :
78
- # <think> in previous, </think> in delta,
79
- # extract reasoning content
80
- end_index = delta_text .find (self .think_end_token )
81
- reasoning_content = delta_text [:end_index ]
82
- content = delta_text [end_index + len (self .think_end_token ):]
83
- content = content if content else None
84
- return reasoning_content , content
85
- elif self .think_end_token_id in previous_token_ids :
86
- # <think> in previous, </think> in previous,
87
- # reasoning content continues
88
- return "" , delta_text
89
- else :
90
- # <think> in previous, no </think> in previous or delta,
91
- # reasoning content continues
92
- return delta_text , ""
93
- elif self .think_start_token_id in delta_token_ids :
94
- if self .think_end_token_id in delta_token_ids :
95
- # <think> in delta, </think> in delta, extract reasoning content
75
+ # </think> in delta
76
+ if self .think_end_token_id in delta_token_ids :
77
+ #<think> in delta, </think> in delta, extract reasoning content
78
+ if self .think_start_token_id in delta_token_ids :
96
79
start_index = delta_text .find (self .think_start_token )
97
- end_index = delta_text .find (self .think_end_token )
80
+ end_index = delta_token_ids .find (self .think_end_token )
98
81
reasoning_content = delta_text [start_index +
99
82
len (self .think_start_token
100
83
):end_index ]
84
+ content = delta_text [end_index + len (self .think_end_token ):]
85
+ return reasoning_content , content
86
+ # <think> in previous, </think> in delta,
87
+ else :
88
+ end_index = delta_text .find (self .think_end_token )
89
+ reasoning_content = delta_text [:end_index ]
101
90
content = delta_text [end_index + len (self .think_end_token ):]
102
91
content = content if content else None
103
92
return reasoning_content , content
104
- else :
105
- # <think> in delta, no </think> in delta,
106
- # reasoning content continues
107
- return delta_text , ""
108
- else :
109
- # thinking is disabled, just content
93
+ # </think> in previous reasoning content continues
94
+ elif self .think_end_token_id in previous_token_ids :
110
95
return "" , delta_text
96
+ # <think> in previous
97
+ elif self .think_start_token_id in previous_token_ids :
98
+ return delta_text ,""
99
+ # <think> in delta
100
+ elif self .think_start_token_id in delta_token_ids :
101
+ start_index = delta_text .find (self .think_start_token )
102
+ reasoning_content = delta_text [start_index + len (self .think_start_token ):]
103
+ content = ""
104
+ return reasoning_content , content
105
+ else :
106
+ return delta_text , ""
107
+
108
+
109
+
110
+
111
111
112
112
def extract_reasoning_content (
113
113
self , model_output : str , request : ChatCompletionRequest
114
114
) -> tuple [Optional [str ], Optional [str ]]:
115
115
"""
116
116
Extract reasoning content from the model output.
117
117
118
- For text abc</think>xyz :
119
- - ' abc' goes to reasoning_content
120
- - ' xyz' goes to content
118
+ 支持两种格式 :
119
+ 1. <think> abc</think>xyz - 标准格式
120
+ 2. abc</think> xyz - 缺少起始标签的格式
121
121
122
122
Returns:
123
123
tuple[Optional[str], Optional[str]]: reasoning content and content
124
124
"""
125
125
126
- # Check if the model output contains the <think> and </think> tokens.
127
- if (self .think_start_token not in model_output
128
- or self .think_end_token not in model_output ):
129
- return None , model_output
130
- # Check if the <think> is present in the model output, remove it
131
- # if it is present.
132
- model_output_parts = model_output .partition (self .think_start_token )
133
- model_output = model_output_parts [2 ] if model_output_parts [
134
- 1 ] else model_output_parts [0 ]
135
- # Check if the model output contains the </think> tokens.
136
- # If the end token is not found, return the model output as is.
126
+ # 检查是否包含结束标签
137
127
if self .think_end_token not in model_output :
138
128
return None , model_output
139
129
140
- # Extract reasoning content from the model output.
141
- reasoning_content , _ , content = model_output .partition (
142
- self .think_end_token )
130
+ # 检查是否有起始标签
131
+ if self .think_start_token in model_output :
132
+ # 标准格式:<think>content</think>answer
133
+ if (self .think_start_token not in model_output
134
+ or self .think_end_token not in model_output ):
135
+ return None , model_output
136
+ # Check if the <think> is present in the model output, remove it
137
+ # if it is present.
138
+ model_output_parts = model_output .partition (self .think_start_token )
139
+ model_output = model_output_parts [2 ] if model_output_parts [
140
+ 1 ] else model_output_parts [0 ]
141
+ # Check if the model output contains the </think> tokens.
142
+ # If the end token is not found, return the model output as is.
143
+ if self .think_end_token not in model_output :
144
+ return None , model_output
145
+
146
+ # Extract reasoning content from the model output.
147
+ reasoning_content , _ , content = model_output .partition (
148
+ self .think_end_token )
149
+
150
+ final_content = content or None
151
+ return reasoning_content , final_content
152
+ else :
153
+ # 缺少起始标签的格式:content</think>answer
154
+ parts = model_output .split (self .think_end_token , 1 )
155
+
156
+ if len (parts ) == 2 :
157
+ reasoning_content = parts [0 ].strip ()
158
+ final_content = parts [1 ].strip () if parts [1 ].strip () else None
159
+ return reasoning_content , final_content
143
160
144
- final_content = content or None
145
- return reasoning_content , final_content
161
+ return None , model_output
0 commit comments