Spaces:
Running
Running
feat(core): enhance reasoning toggle for streaming output
Browse files- [refactor] Simplify initial text type check (utils.py:render_with_reasoning_toggle():310)
- [feat] Implement streaming logic for reasoning removal (utils.py:313-321)
- [feat] Implement streaming logic for reasoning HTML conversion (utils.py:323-331)
- [docs] Update docstring to detail new reasoning toggle behavior (utils.py:302-309)
utils.py
CHANGED
|
@@ -300,33 +300,40 @@ def format_access_denied_message(message: str) -> str:
|
|
| 300 |
def render_with_reasoning_toggle(text: str, show_reasoning: bool) -> str:
|
| 301 |
"""Render assistant text while optionally revealing content inside <think>...</think>.
|
| 302 |
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
"""
|
| 309 |
-
if not isinstance(text, str)
|
| 310 |
return text
|
| 311 |
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
|
|
|
|
|
|
|
|
| 300 |
def render_with_reasoning_toggle(text: str, show_reasoning: bool) -> str:
|
| 301 |
"""Render assistant text while optionally revealing content inside <think>...</think>.
|
| 302 |
|
| 303 |
+
Behavior:
|
| 304 |
+
- When show_reasoning is True:
|
| 305 |
+
* Replace the opening <think> tag with a collapsible HTML <details> block and an opening
|
| 306 |
+
fenced code block. Stream reasoning tokens inside this block as they arrive.
|
| 307 |
+
* Replace the closing </think> tag with the closing fence and </details> when it appears.
|
| 308 |
+
- When show_reasoning is False:
|
| 309 |
+
* Remove complete <think>...</think> blocks.
|
| 310 |
+
* For partial streams (no closing tag yet), trim everything from the first <think> onward.
|
| 311 |
+
|
| 312 |
+
Safe to call on every streamed chunk; conversions are idempotent.
|
| 313 |
"""
|
| 314 |
+
if not isinstance(text, str):
|
| 315 |
return text
|
| 316 |
|
| 317 |
+
# If we are NOT showing reasoning, remove it entirely. For partial streams, hide from <think> onwards.
|
| 318 |
+
if not show_reasoning:
|
| 319 |
+
if "<think>" not in text:
|
| 320 |
+
return text
|
| 321 |
+
if "</think>" not in text:
|
| 322 |
+
return text.split("<think>", 1)[0]
|
| 323 |
+
# Remove complete <think>...</think> blocks
|
| 324 |
+
pattern_strip = re.compile(r"<think>[\s\S]*?</think>", re.IGNORECASE)
|
| 325 |
+
return pattern_strip.sub("", text)
|
| 326 |
+
|
| 327 |
+
# Show reasoning: stream it as it arrives by converting tags into a collapsible details block
|
| 328 |
+
open_block = "<details><summary>Reasoning</summary>\n\n```text\n"
|
| 329 |
+
close_block = "\n```\n</details>\n"
|
| 330 |
+
|
| 331 |
+
# Convert opening tag when first seen; idempotent if it's already converted
|
| 332 |
+
if "<think>" in text:
|
| 333 |
+
text = re.sub(r"<think>", open_block, text, flags=re.IGNORECASE)
|
| 334 |
+
|
| 335 |
+
# Convert closing tag when it appears
|
| 336 |
+
if "</think>" in text:
|
| 337 |
+
text = re.sub(r"</think>", close_block, text, flags=re.IGNORECASE)
|
| 338 |
+
|
| 339 |
+
return text
|