返回

文章详情

在Pi中压缩工作的原理

Hacker News2026年8月13日 17:57

如果你曾在像Pi、Claude Code或Codex这样的编程代理中进行过长时间的编码会话,那么你就触发了压缩。在这篇文章中,我们将解释压缩是如何工作的以及何时Pi需要进行压缩。大型语言模型(LLMs)有有限的上下文窗口。上下文窗口是模型在生成响应时能够“看到”的内容。LLMs使用的变换器架构限制了它们可以处理的输入量。编程代理会话的输入包括所有先前的消息和工具调用,并且随着你的工作而不断增长。一旦它超过了上下文窗口,LLM会拒绝请求。与编程代理(如Pi)互动时,代理向LLM发送请求并接收响应。每个请求都包括系统提示、加载的文件(如AGENTS.md)、工具定义和对话历史。编程代理的第一个LLM请求包含这个初始上下文,以及第一个用户消息。请求1: [系统][工具][用户] 这开始了一个回合。LLM可能先返回一个包含工具调用的助手消息。代理程序执行这些工具调用,并向LLM发送一个新请求,包含完整的对话,现在包括工具的结果。我们收到另一个助手消息。当助手完成生成输出时,这个回合就结束了。请求1之后: [系统][工具][用户][助手:工具调用][工具结果][助手] <-------------------> ^ <---------> 由LLM返回 | 由LLM返回 | 由代理生成 我们继续工作,并发送另一个消息。请求2:[系统][工具][用户][助手:工具调用][工具结果][助手][用户] ^ 新的用户消息 每个回合都扩展了对话。最终,历史会超出上下文限制。下一个请求将返回一个错误,例如请求超出最大大小。[系统][工具][用户][助手][....][工具结果][用户] ^ 超出上下文窗口 上下文溢出处理 当我们无法按原样继续现有对话时,我们有两种选择。我们可以开始一个新的空对话,不带累积的上下文。这将丢弃历史,包括之前的决策和未解决的工作。这样做可能仍然是一个好主意,因为LLM输出的性能会随着上下文大小的增加而降低。我们可以创建一个较小的对话上下文表示,因为我们希望保持这次对话进行。这就是压缩的作用。 压缩 理论上,有很多方法可以实现压缩。例如,我们可以编写一个确定性函数,保留对话中的一些内容并丢弃其余部分。然而在实践中,压缩的实现使用LLM请求来总结对话历史。压缩用压缩表示替换历史的一部分,留出空间以容纳更多消息和工具调用。[系统][工具][压缩结果][用户] ^ 新消息 Pi的实现 让我们更仔细地看看Pi如何具体实现压缩。当对话过长时,Pi会使用压缩来总结旧的内容,同时保留最近的工作。当上下文限制接近上下文窗口的总大小时,压缩会被触发。它也可以通过手动使用/compact命令触发。Pi在回合结束后检查自动压缩。在此之前,每个请求扩展现有提示,并可以重用其缓存前缀。如果Pi遇到上下文溢出错误,它也可能在回合中进行压缩。在压缩时,Pi保留一些数量的最近消息不变。 压缩前:[系统+工具][旧回合][最近保留的消息] 保留消息的数量是可调的,因为Pi使用可配置的令牌预算。Pi当前的默认值为20,000个令牌,大约相当于5到20个回合。所有在此切点之前的消息都会被提取并序列化,并将被总结。 Pi的压缩提示 对于编程代理,良好总结的理想结果类似于一个班次到下一班次的交接简报。Pi的压缩提示专注于现有上下文中有很多不再相关的内容。我们应该只保留对下一个LLM请求仍然重要的上下文。因此,Pi为压缩发送的请求与常规对话不同。用于独立压缩请求的系统提示是不同的。我们不是告诉LLM“你是一个专业的编码助手”,而是告诉LLM“你是一个上下文总结助手。”压缩请求中的用户消息也不同。它请求“在稍后返回时为上下文提供此对话分支的结构化总结。”提示规定了目标、进展和关键决策的部分。这是一个独立请求,不使用任何现有对话历史,这意味着可以使用不同的LLM模型而不会产生不必要的成本。压缩的结果附加到Pi会话作为压缩条目,会话...

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡