乐于分享
好东西不私藏

拆解 Pi 架构:极简 AI 编码代理的设计之道

拆解 Pi 架构:极简 AI 编码代理的设计之道

https://www.youtube.com/watch?v=gTeujlv8qK0

本视频深入讲解了 AI 编码代理 Pi 的完整架构,分为两大模块:PiCore(代理核心) 与 PiInteractive(交互层)。作者强调,Pi 的设计风格是 极简、模块化、完全自研,非常适合学习或二次开发。


第一章:介绍(Intro)

  • Pi 是一个极简且架构优美的 AI 编码代理,近年来广受欢迎。
  • 视频目标:
    1. 理解 PiCore(代理循环,可通过 RPC/SDK 编程调用)
    2. 理解 PiInteractive(终端用户界面 TUI 的交互功能)

第二章:代理循环(Agent Loop)

PiCore 的核心是 每轮对话都执行的一套固定步骤:

  1. 初始化上下文

    • 加载硬编码的 系统提示词(system prompt)
    • 附加 agents.md 文件(位于 home 和当前工作目录)
    • 加载所有 技能(skill)的描述
    • 加载所有 工具(tool)的描述
    • 拼接消息历史(或压缩后的摘要)和当前消息
  2. 转换上下文

    • 判断是否需要 压缩(compaction)
    • 如需要,由 LLM 对历史消息进行总结并替换原消息历史
  3. 调用 LLM

    • 调用用户选择的 LLM(OpenAI GPT-5、Anthropic、Kimi、MiniMax 等)
    • LLM 可能返回 工具调用(读文件、写文件、搜索等)
    • 工具返回结果后,LLM 可继续调用工具(可循环数百次)
    • 当 LLM 不再需要工具时,返回最终响应给用户

关键点:Pi 的整个 agentic loop 完全从零手写,未使用 OpenAI Agents SDK、Vercel AI SDK 等现成库。


第三章:会话与内存(Sessions & Memory)

Pi 的会话存储设计非常优雅:

  • 存储位置:~/.pi/agent/sessions/
  • 按 工作目录 分类存储(如 /dashboard、/weather-app 等)
  • 每个会话使用 JSONL 格式(每行一个 JSON 对象)
    • 优点:新消息只需追加一行,无需重写整个数组
  • 每个消息对象包含:type、id、parent、timestamp、content

亮点:会话不是线性列表,而是 树形结构。通过 parent 字段,可以实现 对话分支(fork)。例如用户从某条消息分叉出两条不同方向的对话。Pi 使用 /tree 命令可视化该结构。

视频中实际演示了:

  • 在终端执行 /tree 查看对话树
  • 在文件系统和 VS Code 中查看 JSONL 文件的内容

第四章:工具(Tools)

Pi 默认仅包含 4 个核心工具:

  • read
     – 读取文件
  • bash
     – 执行 shell 命令
  • edit
     – 编辑文件
  • write
     – 写入文件

极简主义:作者本人会额外添加 web_search 作为第 5 个工具。

另外还有两个 默认禁用的工具:grep 和 find。启用方式:pi --tools read,grep,find → 进入 只读模式,适合程序化调用(RPC 场景)时防止意外修改文件。


第五章:扩展(Extensions)

扩展是可安装的 TypeScript 包,用于修改 Pi 的行为,无需改动核心代码。

扩展可以做到:

  • 注册新工具
  • 订阅事件(工具调用、代理响应、用户消息等)
  • 注册命令与快捷键
  • 添加 CLI 标志
  • 修改系统提示词
  • 渲染自定义消息

安全提示:扩展会执行本地代码,不要安装不可信来源的扩展。可以用 Pi 自身先阅读扩展源码确保安全。


第六章:系统提示词(System Prompt)

Pi 的默认系统提示词非常短(约 20 行),结构如下:

  1. 基本角色设定:"你是 Pi,一个有用的助手"
  2. 追加 append-system.md 的内容(用户可自定义)
  3. 列出所有可用技能(使用类似 markdown 的格式)
  4. 包含当前日期和当前工作目录

用户可通过以下方式覆盖:

  • 创建 .pi/system.md
  • 运行时:pi --system-prompt "你的提示词"

第七章:交互入口点(Interactive Entry Point)

当用户在终端输入 pi 命令时,实际流程:

  1. client.ts
     接收命令,设置进程标题等
  2. 调用 main.ts:
    • 解析参数
    • 解析配置(工作目录等)
    • 加载扩展
    • 创建代理会话
       – 此时才真正初始化 PiCore
    • 运行选定模式:交互模式 / RPC / 直接打印到 STDIO

第八章:终端用户界面(Terminal UI)

Pi 的 TUI 特点:

  • 完全 自研,未使用 Textual 等现成库
  • 基于组件
    ,每个组件负责自己的渲染和输入
  • 组件可动态更新,可订阅 PiCore 发出的事件
  • 界面不闪烁,底部有状态条
  • 设计极简:上方显示消息,下方为输入区

作者强调:你可以用同样的 PiCore 构建自己的 GUI 或 Web UI,Pi 自带的 TUI 只是其中一种实现。


第九章:压缩(Compaction)

Pi 处理上下文窗口超限的方式:

  • 不主动估算 token 数
    (不像某些代理用字符数除以 4 来估算)
  • 而是 依赖 LLM 返回的 usage 信息
  • 在两个时机调用 check_compaction:
    1. 代理结束一个回合(返回响应后)
    2. 用户发送新消息之前

计算上下文 token 数的方式:

  • 如果有 usage.context_tokens 直接使用
  • 否则计算:input_tokens + output_tokens + cache_read + cache_write

压缩提示词 非常结构化,要求 LLM 生成包含以下字段的摘要:

  • 目标(goal)
  • 约束与偏好
  • 进度(已完成、进行中、被阻塞)
  • 关键决策
  • 下一步计划
  • 关键上下文(保留完整文件路径、函数名、错误信息)

视频中现场演示了执行压缩后生成的摘要内容。


第十章:技能(Skills)

技能 与 自定义斜杠命令 是两个不同的东西:

  • 自定义斜杠命令(如 /mycmd):由 CLI 层拦截,直接替换为预设的提示词,不会 进入 PiCore。

  • 技能(Skills):

    • 存放在 .md 文件中,文件头部包含 name 和 description
    • 技能描述被加载到系统提示词中,因此 LLM 知道存在哪些技能
    • 用户通过 /skill:技能名 调用
    • 交互层 不会 自动把技能内容替换进去
    • 而是向 LLM 发送一个特殊结构,包含:技能名称、描述、文件路径
    • LLM 收到后,会使用 read 工具主动读取该技能文件内容,然后继续执行

这种设计与其他代理(如直接粘贴技能内容)不同,体现了 Pi 在分层与 token 效率之间的权衡。


最终总结

观看完本视频后,你应该能够:

  • 理解 Pi 的极简 agentic loop 设计
  • 理解其 JSONL + 树形会话存储方案
  • 了解其工具、扩展、技能、压缩机制的分层实现
  • 有能力自己动手实现一个类似 Pi 的 AI 编码代理

作者寄语:这是一个非常有教育意义的项目,欢迎在评论区提问交流。

相关学习资料