Spaces:
Runtime error
Runtime error
| import re | |
| import time | |
| from config import logger | |
| class ParserState: | |
| __slots__ = ['answer', 'thought', 'in_think', 'in_answer', 'start_time', 'last_pos', 'total_think_time'] | |
| def __init__(self): | |
| self.answer = "" | |
| self.thought = "" | |
| self.in_think = False | |
| self.in_answer = False | |
| self.start_time = 0 | |
| self.last_pos = 0 | |
| self.total_think_time = 0.0 | |
| def format_time(seconds_float): | |
| total_seconds = int(round(seconds_float)) | |
| hours = total_seconds // 3600 | |
| remaining_seconds = total_seconds % 3600 | |
| minutes = remaining_seconds // 60 | |
| seconds = remaining_seconds % 60 | |
| if hours > 0: | |
| return f"{hours}h {minutes}m {seconds}s" | |
| elif minutes > 0: | |
| return f"{minutes}m {seconds}s" | |
| else: | |
| return f"{seconds}s" | |
| def parse_response(text, state): | |
| buffer = text[state.last_pos:] | |
| state.last_pos = len(text) | |
| while buffer: | |
| if not state.in_think and not state.in_answer: | |
| think_start = buffer.find('<think>') | |
| reasoning_start = buffer.find('<reasoning>') | |
| answer_start = buffer.find('<answer>') | |
| starts = [] | |
| if think_start != -1: | |
| starts.append((think_start, '<think>', 7, 'think')) | |
| if reasoning_start != -1: | |
| starts.append((reasoning_start, '<reasoning>', 11, 'think')) | |
| if answer_start != -1: | |
| starts.append((answer_start, '<answer>', 8, 'answer')) | |
| if not starts: | |
| state.answer += buffer | |
| break | |
| start_pos, start_tag, tag_length, mode = min(starts, key=lambda x: x[0]) | |
| state.answer += buffer[:start_pos] | |
| if mode == 'think': | |
| state.in_think = True | |
| state.start_time = time.perf_counter() | |
| else: | |
| state.in_answer = True | |
| buffer = buffer[start_pos + tag_length:] | |
| elif state.in_think: | |
| think_end = buffer.find('</think>') | |
| reasoning_end = buffer.find('</reasoning>') | |
| ends = [] | |
| if think_end != -1: | |
| ends.append((think_end, '</think>', 8)) | |
| if reasoning_end != -1: | |
| ends.append((reasoning_end, '</reasoning>', 12)) | |
| if ends: | |
| end_pos, end_tag, tag_length = min(ends, key=lambda x: x[0]) | |
| state.thought += buffer[:end_pos] | |
| duration = time.perf_counter() - state.start_time | |
| state.total_think_time += duration | |
| state.in_think = False | |
| buffer = buffer[end_pos + tag_length:] | |
| if end_tag == '</reasoning>': | |
| state.answer += buffer | |
| break | |
| else: | |
| state.thought += buffer | |
| break | |
| elif state.in_answer: | |
| answer_end = buffer.find('</answer>') | |
| if answer_end != -1: | |
| state.answer += buffer[:answer_end] | |
| state.in_answer = False | |
| buffer = buffer[answer_end + 9:] | |
| else: | |
| state.answer += buffer | |
| break | |
| elapsed = time.perf_counter() - state.start_time if state.in_think else 0 | |
| return state, elapsed | |
| def format_response(state, elapsed): | |
| answer_part = state.answer | |
| collapsible = [] | |
| collapsed = "<details open>" | |
| if state.thought or state.in_think: | |
| if state.in_think: | |
| total_elapsed = state.total_think_time + elapsed | |
| formatted_time = format_time(total_elapsed) | |
| status = f"💭 Thinking for {formatted_time}" | |
| else: | |
| formatted_time = format_time(state.total_think_time) | |
| status = f"✅ Thought for {formatted_time}" | |
| collapsed = "<details>" | |
| collapsible.append( | |
| f"{collapsed}<summary>{status}</summary>\n\n<div class='thinking-container'>\n{state.thought}\n</div>\n</details>" | |
| ) | |
| return collapsible, answer_part | |
| def remove_tags(text): | |
| if text is None: | |
| return None | |
| return re.sub(r'<[^>]+>', ' ', text).strip() |