import codecs import re def fix_markdown(markdown: str) -> str: return codecs.decode(markdown, 'unicode_escape') # 推理模型(DeepSeek R1、QwQ 等)会把思考过程放进 ... 标签返回; # 部分供应商/网关还会吞掉起始标签只留下 ,或在输出截断时只有起始标签。 # 笔记/问答正文落地前统一剥掉,避免思考过程混进用户可见内容。 _THINK_PAIRED_RE = re.compile(r'.*?', re.IGNORECASE | re.DOTALL) _THINK_ORPHAN_CLOSE_RE = re.compile(r'', re.IGNORECASE) _THINK_UNCLOSED_RE = re.compile(r'.*\Z', re.IGNORECASE | re.DOTALL) def strip_think_blocks(text: str | None) -> str: """剥离模型输出中的思考过程标签,返回干净正文。 覆盖三种形态: - 成对标签:...(含多段、跨行、 变体,大小写不敏感) - 只剩孤立 (起始标签被供应商吃掉):取最后一个闭合标签之后的内容 - 只有 没闭合(输出被截断):丢弃标签起的全部内容 """ if not text: return "" cleaned = _THINK_PAIRED_RE.sub('', text) last_close = None for last_close in _THINK_ORPHAN_CLOSE_RE.finditer(cleaned): pass if last_close: cleaned = cleaned[last_close.end():] cleaned = _THINK_UNCLOSED_RE.sub('', cleaned) return cleaned.strip()