|
77 | 77 | (r"<reasoning>(.*?)</reasoning>", "<reasoning>", "</reasoning>"), |
78 | 78 | # Occasionally seen |
79 | 79 | (r"<reason>(.*?)</reason>", "<reason>", "</reason>"), |
80 | | - # GPT-OSS style (simplified pattern for the analysis channel) |
81 | | - (r"<\|start\|>assistant<\|channel\|>analysis<\|message\|>(.*?)<\|end\|>", |
82 | | - "<|start|>assistant<|channel|>analysis<|message|>", "<|end|>"), |
83 | 80 | ] |
84 | 81 |
|
| 82 | +# GPT-OSS uses a channel-based format: analysis channel for reasoning, final channel for response |
| 83 | +GPT_OSS_ANALYSIS_PATTERN = r"<\|channel\|>analysis<\|message\|>(.*?)<\|end\|>" |
| 84 | +GPT_OSS_FINAL_PATTERN = r"<\|channel\|>final<\|message\|>(.*?)$" |
| 85 | + |
85 | 86 |
|
86 | 87 | class YANCLMStudio: |
87 | 88 | """ |
@@ -338,6 +339,26 @@ def _extract_reasoning_auto(self, text: str) -> Tuple[str, str, Optional[str]]: |
338 | 339 | Tuple of (response_without_reasoning, reasoning_content, detected_pattern) |
339 | 340 | detected_pattern is None if no pattern matched |
340 | 341 | """ |
| 342 | + # Check for GPT-OSS channel-based format first |
| 343 | + # Format: <|channel|>analysis<|message|>...<|end|>...<|channel|>final<|message|>... |
| 344 | + analysis_match = re.search(GPT_OSS_ANALYSIS_PATTERN, text, re.DOTALL) |
| 345 | + if analysis_match: |
| 346 | + reasoning = analysis_match.group(1).strip() |
| 347 | + # Try to extract the final response |
| 348 | + final_match = re.search(GPT_OSS_FINAL_PATTERN, text, re.DOTALL) |
| 349 | + if final_match: |
| 350 | + response = final_match.group(1).strip() |
| 351 | + else: |
| 352 | + # Fallback: remove analysis section and any remaining markers |
| 353 | + response = re.sub(GPT_OSS_ANALYSIS_PATTERN, "", text, flags=re.DOTALL) |
| 354 | + # Clean up any remaining channel markers |
| 355 | + response = re.sub(r"<\|start\|>assistant", "", response) |
| 356 | + response = re.sub(r"<\|channel\|>final<\|message\|>", "", response) |
| 357 | + response = re.sub(r"<\|end\|>", "", response) |
| 358 | + response = response.strip() |
| 359 | + return response, reasoning, "<|channel|>analysis" |
| 360 | + |
| 361 | + # Check standard tag-based patterns |
341 | 362 | for pattern, open_tag, close_tag in COMMON_REASONING_PATTERNS: |
342 | 363 | # Use DOTALL to match across newlines |
343 | 364 | matches = list(re.finditer(pattern, text, re.DOTALL)) |
|
0 commit comments