夜雨聆风学习资料网

ARTICLE · 1197581

Pi 上下文管理机制源码分析

Pi 上下文管理机制源码分析

摘要

Pi 将持久化会话历史与模型可见上下文分离,通过会话树、上下文投影、压缩检查点、结构化摘要和模型调用前的消息转换,实现长会话的容量控制与执行连续性。其工程设计轻量、边界清晰,提供了上下文编辑和扩展入口,本文主要梳理上述机制核心源码的实现原理。

关键词:Pi;Agent Loop;上下文管理;会话投影;上下文压缩;长程任务

一、概述

Pi 是面向软件研发的开源 AI 智能体,本报告分析其会话管理与上下文处理相关源码,重点覆盖会话历史组织、模型上下文构建、压缩与恢复、扩展机制和运行时调用链;分析范围为 Pi 1.3.0 代码路径。

经分析,其核心设计是将完整历史 Hₜ 与当前上下文 Cₜ 分离:Cₜ = P(Hₜ)。P 表示沿当前会话分支、压缩检查点与上下文编辑记录执行的投影与重建操作,而不是完整的语义相关性规划。

二、总体架构与数据模型

上下文逻辑主要分布在 SessionManager、AgentSession 和 Agent Loop 三层。SessionManager 管理会话历史与投影;AgentSession 负责运行调度、阈值检测和压缩恢复;Agent Loop 完成模型请求前的上下文变换与消息格式处理。

模块

主要职责

核心文件

SessionManager

会话树、持久化、分支、上下文投影

session-manager.ts

AgentSession

会话执行、自动压缩、异常恢复

agent-session.ts

Agent Loop

模型调用前的上下文变换与规范化

agent-loop.ts

用户输入 → AgentSession → SessionManager → buildSessionProjection()

→容量检测 / 压缩 → Agent Loop → transformContext()

→convertToLlm() → normalizeContext() → LLM → 工具执行

会话以树形记录保存,每条记录具有 id、parentId、timestamp 和 type 等字段,支持当前分支追溯。压缩检查点通过 summary 和 firstKeptEntryId 记录摘要与原样保留边界,避免对原始会话内容进行破坏性覆盖。

interface SessionEntryBase {

type:string;

id:string;

parentId:string | null;

timestamp:string;

}

interface CompactionEntryextends SessionEntryBase {

type:"compaction";

summary:string;

firstKeptEntryId:string;

tokensBefore:number;

details?:T;

usage?:Usage;

fromHook?:boolean;

systemMessage?:SystemMessage;

}

源码:packages/coding-agent/src/core/session-manager.ts(SessionEntryBase、CompactionEntry)。

三、上下文关键实现机制

(一)上下文投影与历史编辑

buildSessionProjection() 先通过 buildSessionPath() 追溯当前叶子节点所在的历史路径,再由 buildContextEntries() 定位压缩检查点与有效消息范围,最后应用上下文编辑记录,得到模型当前可见的消息列表。

const path = buildSessionPath(entries, leafId, byId);

const { thinkingLevel, model } = getSessionContextSettings(path);

const contextEntries = buildContextEntries(entries, leafId, byId);

较早历史以摘要代替,近期消息保持原样,会话树使不同分支的数据不会自动混合;ContextEditEntry 可以指向一条原始消息,设置新的内容,或使用 null 将其从当前投影中省略,原始记录仍然保留;适合用来压缩冗长的工具输出、替换过时上下文和清理重复信息。

interface ContextEditEntry extends SessionEntryBase {

type:"context_edit";

targetId:string;

replacement:{ content: ContextEditableContent } | null;

}

if (!edit) return messages;

if (edit.replacement === null) return [];

源码:session-manager.ts(buildSessionPath、buildContextEntries、buildSessionProjection、projectContextEntry)。

(二)容量检测与压缩触发

Pi 根据模型上下文窗口 W、预留 Token 数 R 和当前估算使用量 Uₜ 判断是否压缩,触发条件为 Uₜ > W − R。除阈值触发外,还具备模型上下文溢出后的压缩与恢复路径。

export function shouldCompact(

contextTokens:number,

contextWindow:number,

settings:CompactionSettings

): boolean {

if(!settings.enabled) return false;

returncontextTokens > contextWindow - settings.reserveTokens;

}

estimateProjectedContextTokens() 优先使用模型调用的实际用量;当压缩或上下文编辑导致历史用量失效时重新估算。纯文本估算中使用过按字符数除以四的近似方法,不能视为所有模型的精确 Token 计数。

源码:compaction.ts(shouldCompact、estimateProjectedContextTokens);agent-session.ts(_runAutoCompaction、_compactBeforeNextAssistantResponse)。

(三)压缩切分与结构化摘要

prepareCompaction() 基于当前上下文投影确定压缩范围。findProjectedCutPoint() 等函数从最新消息向前累计 Token,按照 keepRecentTokens 预算保留近期历史,同时处理单轮交互内部大量工具调用造成的超长上下文。

accumulatedTokens += messageTokens;

if (accumulatedTokens >= keepRecentTokens) {

cutIndex= cutPoints.find(candidate => candidate >= i)

??cutPoints[cutPoints.length - 1];

break;

}

压缩摘要由模型生成,模板要求保留 Goal、Constraints & Preferences、Progress(Done / In Progress / Blocked)、Key Decisions、Next Steps 和 Critical Context 等信息。对于重复压缩,系统根据是否存在 previousSummary 选择初次摘要或增量更新提示词。

let basePrompt = previousSummary

?UPDATE_SUMMARIZATION_PROMPT

:SUMMARIZATION_PROMPT;

Sₜ = Update(Sₜ₋₁, ΔHₜ)

相较于原始消息的简单截断,结构化摘要更有利于保持任务连续性,但仍是有损转换。关键约束、精确代码定位和校验结果在反复压缩中可能遗漏,不宜完全依赖摘要承担权威任务状态。压缩还跟踪文件读取、修改等操作信息,为后续编程任务提供背景。

源码:compaction.ts(findCutPoint、findProjectedCutPoint、prepareCompaction、generateSummaryWithUsage、compact)。

(四)模型调用前转换及扩展

Agent Loop 在调用模型前依次执行 transformContext、convertToLlm 和 normalizeContext,分别承担可选上下文变换、内部消息格式转换和请求规范化。transformContext 是二次开发的基础扩展点,但 Pi 默认接口并不自动提供目标规划、知识检索与信息相关性排序。

let messages = context.messages;

if (config.transformContext) {

messages= await config.transformContext(messages, signal);

}

const llmMessages = await config.convertToLlm(messages);

const llmContext = normalizeContext({ messages: llmMessages });

此外,session_before_compact 扩展事件允许在压缩前介入,按业务规则取消压缩或提供自定义压缩结果;此机制能够承载对审计规则、编程约束、本体建模规范等关键信息的保护策略。

源码:packages/agent/src/agent-loop.ts(streamAssistantResponse);packages/agent/src/agent.ts(transformContext);agent-session.ts(session_before_compact)。

四、总结

Pi 通过会话树、上下文投影、压缩检查点、结构化摘要与调用前转换,实现了工程上较为完整的上下文基础管理体系,其主要价值是将“完整历史”和“模型当前可见信息”分离,并为压缩与编辑提供轻量、可扩展的实现。其优势在于:会话历史与运行时视图解耦,保留可追溯性;使用 Token 预算和增量摘要控制开销;通过树形会话和检查点支持分支与恢复;为上下文编辑、转换及压缩预留可扩展入口。

分析维度

已有机制

主要不足

目标管理

摘要保留 Goal

缺少独立、可校验的目标状态

历史组织

会话树、投影、编辑

默认缺少任务语义相关性评分

执行状态

会话记录与摘要

缺少统一的结构化进度与证据模型

压缩质量

保留近期消息、增量摘要

多轮压缩存在信息损失风险

知识与记忆

支持扩展接入

缺少默认的统一精准供给策略

闭环纠偏

工具执行反馈

缺少目标偏差驱动的上下文重规划

附录:关键源码索引

会话管理、投影和编辑·packages/coding-agent/src/core/session-manager.ts

压缩算法、摘要及切分·packages/coding-agent/src/core/compaction/compaction.ts

压缩运行调度·packages/coding-agent/src/core/agent-session.ts

Agent Loop 请求前转换·packages/agent/src/agent-loop.ts

Agent 配置与转换接口·packages/agent/src/agent.ts

分支摘要·packages/coding-agent/src/core/compaction/branch-summarization.ts

相关学习资料