
如果你正在使用或关注各类 AI Agent 框架尤其是像 Pi 这样的对话式 AI你可能已经发现了一个普遍存在的体验问题对话太“啰嗦”了。无论是让 AI 帮你写代码、分析问题还是规划任务它常常会事无巨细地输出每一步的“思考过程”。这些中间推理步骤对于调试和理解 AI 逻辑很有价值但对于只想快速获取最终答案的用户来说却成了干扰信息。你需要在一大段“让我想想…”、“首先…”、“然后…”的文字中费力地寻找那个最终的代码块或结论。这不仅仅是 Pi 的问题而是当前许多以“思考链”Chain-of-Thought为卖点的 AI 产品的通病。它们展示了能力却牺牲了对话的简洁性和最终答案的“可读性”。想象一下在团队协作中你分享一个 AI 生成的解决方案却需要队友先读完几百字的推理才能看到关键代码这无疑降低了信息传递的效率。本文要解决的正是这个痛点。我们将为 Pi或任何具有类似特性的 AI 模型/框架实现一个“思考折叠”功能。这不是一个简单的文本隐藏而是一个智能的后处理流程它能自动识别并结构化 AI 输出的“思考过程”与“最终答案”将前者折叠起来让后者清晰、突出地呈现。读完本文你将获得一个清晰的判断“思考折叠”不是一个炫技功能而是提升 AI 工具可用性和团队协作效率的刚需。一套完整的解决方案从原理分析、技术选型到代码实现手把手教你构建这个功能。可直接复用的代码提供 Python 核心实现并讨论如何集成到不同平台Web 前端、CLI 工具、API 服务。深入的最佳实践如何定义“思考”与“答案”的边界如何处理不同风格的 AI 输出有哪些潜在的陷阱我们不止步于“是什么”更要讲清楚“为什么重要”以及“如何做好”。让我们开始吧。1. 这篇文章真正要解决的问题从“展示过程”到“交付结果”在深入代码之前我们必须先厘清问题的本质。AI 的“思考过程”输出源于其工作模式——尤其是基于 Transformer 的大语言模型它们通过生成下一个词的概率来逐步构建回答。当被要求展示推理时它们会模拟人类的逐步分析。核心矛盾在于生成过程的“透明性”与消费结果的“简洁性”之间的冲突。对开发者/调试者透明性至关重要。我需要看到 AI 是如何分解问题、调用工具、处理异常的这有助于我信任其结果、调整提示词或修复逻辑错误。对最终用户/协作者简洁性是第一位的。我关心的是“最终方案是什么”、“代码能不能直接运行”、“结论清不清晰”。冗长的中间过程是噪音。传统的做法是二选一要么让 AI 只输出最终答案牺牲可解释性要么让它输出全部过程牺牲可读性。而“思考折叠”旨在实现“鱼与熊掌兼得”默认视图用户看到的是干净、专业的最终答案。按需展开如果用户对推理过程存疑或想学习 AI 的思考方式可以一键展开查看完整的思考链。这带来的价值是立体的提升用户体验聊天界面更清爽重点更突出。增强协作效率分享 AI 产出的内容时接收方能更快抓住重点。保留调试能力为开发者保留了深入探查的通道不影响日常使用。因此实现“思考折叠”不是一个简单的 UI 特效其技术核心在于“如何准确、可靠地从混合文本中分离出‘思考’与‘答案’”。这是本文要攻克的主要技术挑战。2. 基础概念与核心原理在动手之前我们需要定义几个关键概念并分析可行的技术路径。2.1 关键概念定义原始输出 (Raw Output)AI 模型直接生成的、包含完整思考链的文本。例如用户问“用 Python 计算斐波那契数列的前10项。”AI 原始输出可能为 “我来帮你写这个程序。首先斐波那契数列的定义是前两项为0和1后续每一项是前两项之和。所以我们需要一个列表来存储结果并用循环来计算。让我想想...可以用for循环也可以考虑递归但递归效率低。这里我选择用循环实现。代码如下def fibonacci(n): fib [0, 1] for i in range(2, n): fib.append(fib[-1] fib[-2]) return fib[:n] print(fibonacci(10))运行这段代码就会输出[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]。”思考过程 (Thinking Process)AI 输出中用于解释、推理、规划、自我纠正的部分。通常以叙述性、描述性的自然语言呈现不包含最终的、可执行的解决方案。如上例中“我来帮你...”、“首先...”、“让我想想...”、“这里我选择...”等段落。最终答案 (Final Answer)AI 输出的核心交付物。对于编程问题是代码块对于知识问答是总结性陈述对于数据分析可能是结论或图表描述。如上例中的代码块和print语句及输出结果。思考折叠 (Thinking Collapse)一个后处理流程其输入是原始输出输出是经过结构化的数据包含被标记的思考过程和最终答案并通常伴随着一个视图逻辑默认隐藏思考过程仅展示最终答案。2.2 核心原理如何分离思考与答案分离策略的准确性直接决定了功能的可用性。主要有三种思路难度和效果递增基于规则与启发式 (Rule-based Heuristic)原理寻找文本中的模式标记。例如思考过程可能包含“我想”、“首先”、“其次”、“因此”等词最终答案可能由特定的标记引出如“答案是”、“代码如下”、“结论是”。代码块可以通过 “” 来识别。优点实现简单速度快对于格式规范的输出如严格要求 AI 用“思考”和“答案”分隔非常有效。缺点泛化能力差。AI 的输出风格多变规则容易漏判或误判。基于模型微调 (Fine-tuning)原理收集大量 AI 的原始输出数据人工标注出“思考”和“答案”的片段。然后用这些数据训练一个文本分类模型如 BERT、RoBERTa让它学会区分两类文本。优点准确率高能理解语义泛化能力强。缺点需要标注数据训练成本高部署需要额外的模型服务响应延迟较高。基于大语言模型自身 (Self-Refinement with LLM)原理利用一个通常是更强的LLM 作为“裁判”对原始输出进行解析和结构化。通过设计精妙的提示词Prompt要求 LLM 按照指定格式如 JSON输出思考部分和答案部分。优点极其灵活无需训练可以处理极其复杂和多样化的输出格式准确率通常很高。缺点成本最高需要调用 LLM API速度最慢依赖提示词工程。我们的选择对于大多数个人开发者或中小型项目方案1规则启发式与方案3LLM解析结合是最务实的选择。我们可以先用一套稳健的规则如识别代码块、特定关键词处理大部分情况对于规则无法处理的复杂情况再降级到使用 LLM 进行解析。本文将以“规则为主LLM为辅”的混合策略进行实现。3. 环境准备与前置条件我们将使用 Python 作为实现语言因为它有丰富的 NLP 和 AI 生态库。以下是基础环境操作系统Windows 10/11, macOS, 或 Linux (如 Ubuntu 20.04)。Python 版本 3.8。包管理工具pip。3.1 创建项目与虚拟环境首先创建一个干净的项目目录并设置虚拟环境避免包冲突。# 创建项目目录 mkdir pi-thinking-collapse cd pi-thinking-collapse # 创建虚拟环境 (以 venv 为例) python -m venv venv # 激活虚拟环境 # Windows (PowerShell) .\venv\Scripts\Activate.ps1 # macOS/Linux source venv/bin/activate3.2 安装核心依赖我们将安装以下库openai用于降级处理时调用 GPT 等模型 API。regex功能比标准re更强大的正则表达式库处理复杂文本模式。pydantic用于数据验证和设置管理让我们的代码更健壮。pip install openai regex pydantic如果计划未来加入更复杂的规则或本地模型还可以考虑transformers,torch等但本文核心实现暂不需要。3.3 获取 API 密钥备用我们的降级策略会用到 OpenAI API或其他兼容 API如 Azure OpenAI。请准备好你的 API Key。访问 OpenAI Platform 创建 API Key。重要安全提示永远不要将 API Key 硬编码在代码或提交到版本控制系统如 Git。应使用环境变量或配置文件管理。# 在终端中设置环境变量 (临时) # Windows (PowerShell) $env:OPENAI_API_KEY your-api-key-here # macOS/Linux export OPENAI_API_KEYyour-api-key-here4. 核心流程拆解与架构设计我们的“思考折叠”处理器将遵循一个清晰的管道Pipeline模式易于理解和扩展。原始文本输入 | v [1. 文本预处理] (清理空白字符规范化换行) | v [2. 规则引擎] (尝试用规则分离思考与答案) |----------------------| | (成功) | (失败) v v [3. 输出结构化数据] [4. LLM 降级解析] | | |----------------------| v [5. 结果整合与后处理] | v 结构化输出 (思考片段列表, 答案片段列表)每一步的职责文本预处理确保输入文本格式一致为后续规则匹配创造良好条件。规则引擎核心模块。按优先级应用一系列规则如“代码块检测”、“关键词分割”一旦某条规则成功匹配并产生可信的分割结果则立即返回不再执行后续规则。LLM 降级解析当所有规则都失败时调用配置好的 LLM API通过精心设计的提示词请求模型对文本进行结构化解析。结果整合与后处理将规则引擎或 LLM 解析的结果统一转换为内部数据结构并进行必要的清理如去除空白片段。这种设计保证了效率优先使用快速规则和鲁棒性LLM 兜底。5. 完整代码实现我们将按照上述架构逐步实现各个模块。所有代码将放在一个名为thinking_collapser.py的文件中。5.1 定义数据结构首先我们使用 Pydantic 来定义清晰的数据模型这有助于类型提示和验证。# thinking_collapser.py from typing import List, Optional, Literal from pydantic import BaseModel, Field class TextSegment(BaseModel): 表示文本中的一个片段可以是思考或答案。 content: str type: Literal[thought, answer] # 片段类型 index: int # 在原始文本中的大致顺序 class CollapseResult(BaseModel): 思考折叠处理器的输出结果。 original_text: str thoughts: List[TextSegment] Field(default_factorylist) # 思考片段列表 answers: List[TextSegment] Field(default_factorylist) # 答案片段列表 separator_used: Optional[str] None # 成功使用的分隔符规则 processed_by: Literal[rules, llm] # 标识由哪个处理器处理 success: bool property def final_answer_text(self) - str: 获取拼接后的最终答案文本最常用的属性。 return \n\n.join([seg.content for seg in self.answers if seg.content.strip()])5.2 实现规则引擎规则引擎包含一系列规则每条规则都是一个函数接收文本返回Optional[CollapseResult]。我们实现几条最常用且有效的规则。# thinking_collapser.py (续) import re import regex # 使用 regex 支持更复杂的模式 class RuleEngine: def __init__(self): self.rules [ self._rule_code_block_delimiter, self._rule_keyword_separator, self._rule_final_answer_marker, ] def process(self, text: str) - Optional[CollapseResult]: 按顺序应用规则返回第一个成功的结果。 for rule_func in self.rules: result rule_func(text) if result and result.success: return result return None def _rule_code_block_delimiter(self, text: str) - Optional[CollapseResult]: 规则1基于代码块 () 进行分割。 假设最后一个代码块之后的内容是答案的核心之前的内容是思考。 这是一种非常常见且有效的模式。 # 使用 regex 查找所有代码块及其位置 pattern r[\s\S]*? matches list(regex.finditer(pattern, text, regex.MULTILINE | regex.DOTALL)) if not matches: return None # 没有代码块此规则不适用 # 以最后一个代码块的结束位置为界 last_match matches[-1] split_index last_match.end() thought_text text[:split_index].strip() answer_text text[split_index:].strip() # 构建结果 thoughts [TextSegment(contentthought_text, typethought, index0)] if thought_text else [] answers [TextSegment(contentanswer_text, typeanswer, index1)] if answer_text else [] return CollapseResult( original_texttext, thoughtsthoughts, answersanswers, separator_usedcode_block, processed_byrules, successTrue ) def _rule_keyword_separator(self, text: str) - Optional[CollapseResult]: 规则2寻找常见的关键词分隔符如“答案是”、“最终结论是”、“代码如下”等。 # 定义可能的分隔符模式优先级从高到低 separator_patterns [ r^(.*?)(?:答案是|最终答案|输出如下|代码如下|结论如下)[:]\s*\n?(.*)$, r^(.*?)(?:所以|因此|综上所述)[,]\s*(.*)$, ] for pattern in separator_patterns: match regex.match(pattern, text, regex.DOTALL) if match: thought_text, answer_text match.group(1).strip(), match.group(2).strip() if answer_text: # 确保答案部分非空 thoughts [TextSegment(contentthought_text, typethought, index0)] if thought_text else [] answers [TextSegment(contentanswer_text, typeanswer, index1)] return CollapseResult( original_texttext, thoughtsthoughts, answersanswers, separator_usedpattern, processed_byrules, successTrue ) return None def _rule_final_answer_marker(self, text: str) - Optional[CollapseResult]: 规则3处理一些AI框架如LangChain常用的特殊标记例如“Final Answer:”。 marker Final Answer: if marker in text: parts text.split(marker, 1) thought_text parts[0].strip() answer_text parts[1].strip() thoughts [TextSegment(contentthought_text, typethought, index0)] if thought_text else [] answers [TextSegment(contentanswer_text, typeanswer, index1)] return CollapseResult( original_texttext, thoughtsthoughts, answersanswers, separator_usedfinal_answer_marker, processed_byrules, successTrue ) return None5.3 实现 LLM 降级解析器当规则引擎失败时我们调用 LLM。这里以 OpenAI GPT-3.5/4 为例。# thinking_collapser.py (续) import os import json from openai import OpenAI class LLMFallbackParser: def __init__(self, api_key: Optional[str] None, model: str gpt-3.5-turbo): self.client OpenAI(api_keyapi_key or os.getenv(OPENAI_API_KEY)) if not self.client.api_key: raise ValueError(OpenAI API key must be provided or set in OPENAI_API_KEY environment variable.) self.model model def parse(self, text: str) - Optional[CollapseResult]: 使用 LLM 解析文本提取思考和答案部分。 prompt f 你是一个专业的文本解析器。请将以下 AI 助手的回复内容严格地分为“思考过程”和“最终答案”两部分。 思考过程包含助手在得出最终答案前的所有推理、分析、计划、自我质疑等内部思维语言。 最终答案包含助手最终给出的直接解决方案、代码、结论或总结性陈述。 要求 1. 以纯 JSON 格式输出且只输出 JSON不要有任何其他解释。 2. JSON 结构必须如下{{thoughts: [思考段落1, 思考段落2, ...], answers: [答案段落1, 答案段落2, ...]}} 3. 尽量保持原文的段落结构。如果原文没有明确的思考或答案则将全部内容放入最合适的类别。 AI 回复内容{text} try: response self.client.chat.completions.create( modelself.model, messages[{role: user, content: prompt}], temperature0.1, # 低温度保证输出稳定 response_format{type: json_object} # 强制 JSON 输出 ) result_json json.loads(response.choices[0].message.content) thoughts [ TextSegment(contentseg, typethought, indexi) for i, seg in enumerate(result_json.get(thoughts, [])) if seg.strip() ] answers [ TextSegment(contentseg, typeanswer, indexi len(thoughts)) for i, seg in enumerate(result_json.get(answers, [])) if seg.strip() ] return CollapseResult( original_texttext, thoughtsthoughts, answersanswers, separator_usedllm_json, processed_byllm, successbool(answers) # 至少有一个答案片段才算成功 ) except Exception as e: print(fLLM 解析失败: {e}) return None5.4 实现主处理器现在将规则引擎和 LLM 解析器组合起来。# thinking_collapser.py (续) class ThinkingCollapser: def __init__(self, llm_fallback_enabled: bool True, openai_api_key: Optional[str] None): self.rule_engine RuleEngine() self.llm_parser None if llm_fallback_enabled: self.llm_parser LLMFallbackParser(api_keyopenai_api_key) def collapse(self, text: str) - CollapseResult: 主处理函数。 if not text or not text.strip(): return CollapseResult( original_texttext, thoughts[], answers[], processed_byrules, successFalse ) # 1. 尝试规则引擎 rule_result self.rule_engine.process(text) if rule_result and rule_result.success: return rule_result # 2. 规则失败尝试 LLM 降级解析 if self.llm_parser: llm_result self.llm_parser.parse(text) if llm_result and llm_result.success: return llm_result elif llm_result: # LLM 处理了但未成功分离例如认为全是思考或全是答案 return llm_result # 3. 全部失败将整个文本视为答案兜底 return CollapseResult( original_texttext, thoughts[], answers[TextSegment(contenttext.strip(), typeanswer, index0)], separator_usedfallback, processed_byrules, successTrue # 仍算成功只是未分离 )5.5 使用示例与测试让我们写一个简单的测试脚本来验证功能。# example_usage.py from thinking_collapser import ThinkingCollapser def main(): # 初始化处理器启用 LLM 降级需要设置 OPENAI_API_KEY 环境变量 collapser ThinkingCollapser(llm_fallback_enabledTrue) # 测试用例1包含代码块的典型输出 test_text_1 我来帮你写一个 Python 函数来计算阶乘。 首先我们需要理解阶乘的定义n! 1 * 2 * ... * n。特别地0! 1。 我们可以用循环来实现也可以使用递归。递归的代码更简洁但可能存在栈溢出风险。这里我展示循环版本。 代码如下 python def factorial(n): if n 0: raise ValueError(阶乘未定义负数) result 1 for i in range(1, n 1): result * i return result print(factorial(5)) # 输出 120你可以直接调用这个函数。 # 测试用例2使用关键词分隔的文本 test_text_2 用户的问题是询问法国的首都。法国的首都是巴黎这是一个位于法国北部的世界著名城市。答案是巴黎。# 测试用例3复杂、无明确标记的文本将触发 LLM 解析 test_text_3 要解决这个问题我们需要先理解用户的需求。用户想要一个快速排序算法的示例。快速排序是一种分治算法平均时间复杂度是 O(n log n)。它的核心思想是选择一个‘基准’元素将数组分成两部分。我决定用 Python 实现因为它表达清晰。注意处理递归基例。好了现在给出代码。def quicksort(arr):... test_cases [(含代码块, test_text_1), (关键词分隔, test_text_2), (复杂文本, test_text_3)] for name, text in test_cases: print(f\n{*50}) print(f测试用例: {name}) print(f{*50}) print(原始文本:) print(text[:200] ... if len(text) 200 else text) print(f\n{*50}) result collapser.collapse(text) print(f处理方式: {result.processed_by}) print(f使用分隔符: {result.separator_used}) print(f成功: {result.success}) print(\n--- 思考过程 (折叠部分) ---) for seg in result.thoughts: print(f[{seg.type.upper()}] {seg.content[:100]}...) print(\n--- 最终答案 (展示部分) ---) print(result.final_answer_text)ifname main: main()运行这个测试脚本 bash python example_usage.py6. 运行结果与效果验证运行example_usage.py你期望看到类似以下的输出LLM 解析部分的结果可能因模型略有差异 测试用例: 含代码块 原始文本: 我来帮你写一个 Python 函数来计算阶乘。 首先我们需要理解阶乘的定义n! 1 * 2 * ... * n。特别地0! 1。 我们可以用循环来实现也可以使用递归。递归的代码更简洁但可能存在栈溢出风险。这里我展示循环版本。 代码如下 python def factorial(n): if n 0: raise ValueError(阶乘未定义负数) result 1 for i in range(1, n 1): result * i return result print(factorial(5)) # 输出 120你可以直接调用这个函数。 处理方式: rules 使用分隔符: code_block 成功: True--- 思考过程 (折叠部分) --- [THOUGHT] 我来帮你写一个 Python 函数来计算阶乘。 首先我们需要理解阶乘的定义n! 1 * 2 * ... * n。特别地0! 1。 我们可以用循环来实现也可以使用递归。递归的代码更简洁但可能存在栈溢出风险。这里我展示循环版本。 代码如下def factorial(n): if n 0: raise ValueError(阶乘未定义负数) result 1 for i in range(1, n 1): result * i return result print(factorial(5)) # 输出 120 ... --- 最终答案 (展示部分) --- 你可以直接调用这个函数。验证要点规则引擎生效对于测试用例1它正确地识别到最后一个代码块结束的位置并将之后的一句“你可以直接调用这个函数。”识别为最终答案。思考部分包含了所有推理和代码。答案提取result.final_answer_text属性直接给出了拼接后的答案文本非常干净。处理方式标识processed_by字段清楚地告诉我们这次是rules处理的。对于测试用例2规则引擎应成功匹配“答案是”模式。对于测试用例3由于没有明确标记规则引擎会失败然后调用 LLM 进行解析processed_by会显示llm。如何判断成功检查result.success是否为True。检查result.answers列表是否非空并且其内容确实是用户期望的“最终答案”。观察result.final_answer_text是否去除了冗长的思考过程显得精炼。如果失败第一步应该看哪里查看processed_by如果是rules说明规则没匹配上。需要检查原始文本格式考虑添加或调整规则。查看separator_used了解是哪个规则生效了这有助于理解处理逻辑。检查原始文本是否包含非常规的格式或标记AI 的输出是否过于自由完全没有结构检查 LLM 解析如果启用了 LLM 降级但失败了查看控制台是否有LLM 解析失败的错误日志通常是 API 密钥、网络或额度问题。7. 常见问题与排查思路在实际集成和使用中你可能会遇到以下问题问题现象可能原因排查方式解决方案规则引擎完全无法分割所有内容都被归为答案。1. AI 输出格式与现有规则不匹配。2. 文本预处理可能改变了关键标记。1. 打印出原始文本检查是否有“”、“答案是”等预期标记。2. 在_rule_code_block_delimiter等函数内添加调试打印查看匹配结果。1. 根据常见的 AI 输出风格添加新的规则函数到RuleEngine.rules列表中。2. 调整正则表达式模式使其更宽松或更精确。LLM 降级解析被调用但返回的 JSON 格式错误或内容为空。1. 提示词Prompt不够清晰导致 LLM 不按格式输出。2. LLM 模型能力不足或温度temperature设置过高。3. API 调用失败网络、鉴权、额度。1. 检查LLMFallbackParser.parse方法中的prompt变量内容。2. 查看response.choices[0].message.content原始返回。3. 捕获并打印try-except块中的异常信息。1. 优化提示词明确要求纯 JSON 输出并给出更具体的“思考”与“答案”的例子。2. 使用更强大的模型如gpt-4并将temperature设为 0 或 0.1。3. 检查 API 密钥和环境变量确认网络连通性。处理速度慢尤其是简单文本。LLM 降级解析被频繁触发而 LLM API 调用延迟很高。1. 检查日志确认简单文本是否也走了processed_by: llm路径。2. 分析规则引擎的匹配顺序和成功率。1. 优化规则引擎将最通用、命中率最高的规则放在前面。2. 对于明确不需要 LLM 的场景可以在初始化ThinkingCollapser时设置llm_fallback_enabledFalse。3. 考虑对文本进行长度或复杂度判断过短的文本直接走兜底逻辑。思考与答案分割不准确例如把部分答案划入了思考。规则或 LLM 对边界的判断有误。1. 分析出错案例的原始文本找到模糊的边界点。2. 查看result.thoughts和result.answers的具体内容。1. 对于规则引擎可以调整分割逻辑例如不是以最后一个代码块结尾而是寻找“输出如下”之后的第一个代码块。2. 对于 LLM在提示词中提供更明确的边界定义例如“最终答案从给出具体代码或结论的句子开始”。3. 实施一个后处理步骤对分割结果进行简单的启发式修正如答案开头不应是“我想”、“那么”等词。集成到 Web 前端后折叠/展开功能状态混乱。前端组件状态管理与后端返回的数据结构不同步。1. 检查后端 API 返回的CollapseResultJSON 结构是否稳定。2. 检查前端是否根据thoughts数组的长度来决定是否显示“展开”按钮。1. 确保 API 返回的数据模型Pydantic Model被正确序列化为 JSON。2. 前端应为每个TextSegment生成一个独立的可折叠区域并用index字段保持顺序。3. 如果thoughts为空则前端根本不渲染折叠控件。8. 最佳实践与工程建议将“思考折叠”功能投入生产环境或团队项目时请考虑以下建议规则优先LLM 兜底始终坚持本架构。LLM API 调用有成本和延迟应作为最后手段。不断丰富和优化你的规则库是提升性能和降低成本的关键。配置化规则管理不要将规则硬编码在RuleEngine类中。可以考虑将规则模式正则表达式、名称和优先级存储在配置文件如 YAML或数据库中实现动态加载和更新。缓存机制对于内容平台或高频使用的场景可以对处理结果进行缓存。以原始文本的哈希值如 MD5为键缓存CollapseResult。这能极大减少对规则引擎和 LLM 的重复调用。异步处理如果集成在 Web 服务器中collapse方法特别是其中的 LLM 调用应该是异步的使用async/await避免阻塞主线程。可以使用aiohttp或openai的异步客户端。前端实现建议组件设计实现一个通用的CollapsibleContent组件接收thoughts和answers数据。默认状态thoughts折叠隐藏answers完全展示。平滑交互展开/折叠应有平滑的动画过渡。持久化可以考虑使用localStorage记录用户对某类内容如“始终展开代码思考”的偏好。安全与边界输入清理对输入的text进行基本的清理和长度限制防止超长文本或恶意输入导致性能问题或 API 滥用。API 密钥管理LLM API 密钥必须通过环境变量或安全的密钥管理服务获取绝不能出现在客户端代码或版本历史中。错误降级确保即使 LLM 服务完全不可用系统也能通过规则引擎或最终的兜底逻辑返回一个可用的结果即使只是不折叠。测试与监控构建测试集收集各种风格的 AI 输出样本代码问答、知识问答、创意写作、数据分析等为每个样本标注期望的“思考/答案”分割点用于单元测试和回归测试。监控指标记录规则引擎与 LLM 的调用比例、成功率、平均处理时间。这能帮助你了解规则的有效性和成本构成。与特定 AI 框架集成如果你是基于 LangChain、LlamaIndex 或类似框架构建应用最好的方式不是后处理而是在生成过程中就进行标记。许多框架支持在Agent或Chain的输出中附加元数据。你可以在提示词中严格要求 AI 使用如thought.../thought和answer.../answer的 XML 标签来分隔内容这样后处理就变成了简单的 XML 解析100% 准确且零成本。9. 总结与后续方向本文详细阐述了为 AI 对话实现“思考折叠”功能的完整技术路径。我们从用户体验痛点出发定义了问题的核心是“过程”与“结果”的分离并提出了一个以规则引擎为主、LLM 解析为辅的混合解决方案。本文的核心交付物一个可运行的 Python 包结构包含ThinkingCollapser核心类、RuleEngine、LLMFallbackParser以及清晰的数据模型。一套可扩展的规则体系你完全可以在此基础上根据你所用的 AI 模型如 Pi、Claude、GPT的常见输出风格添加更多、更精准的规则。一个具备降级能力的健壮架构即使面对最自由、最无结构的 AI 输出也有 LLM 作为最后保障。从原理到部署的全程指南包括环境准备、代码实现、测试验证、问题排查和工程化建议。读者下一步可以如何实践直接使用将thinking_collapser.py复制到你的项目中按照示例初始化并使用collapse方法即可快速获得结构化结果。定制规则观察你常用的 AI 工具的输出习惯在RuleEngine中添加针对性的规则例如处理特定框架的Action:、Observation:标记。集成到前端将处理后的CollapseResult通过 API 返回给前端并实现一个美观的折叠/展开 UI 组件。探索更优的 LLM 提示词本文提供的提示词是一个起点。你可以尝试 few-shot learning在提示词中提供几个分割完美的例子可能会让 LLM 的解析质量更高。值得继续深入的方向多模态内容处理当 AI 的输出包含图片、表格描述时如何折叠其“思考过程”流式输出的实时折叠在 AI 逐字生成回答时能否实时判断并折叠已完成的思考部分基于本地小模型的分类器如果担心成本或延迟可以尝试用scikit-learn训练一个轻量级的文本分类模型来替代部分规则和 LLM 调用。用户偏好学习记录用户对自动折叠结果的纠正行为例如用户手动展开了某段被误判为答案的思考用以优化规则或微调模型。“思考折叠”是一个小而美的功能它背后是对人机交互效率的深刻思考。实现它不仅能让你使用的 AI 工具变得更友好也能让你更深入地理解如何设计并构建与 AI 协同的下一代应用界面。