Skip to content

Repository files navigation

Pi Agent 学习与架构实践

这是一个 TypeScript ESM 项目,用 @earendil-works/pi-ai@earendil-works/pi-agent-core 从模型调用逐步构建工具、上下文、memory、workflow、多模型路由以及 Fastify 前后端 Agent 架构。

仓库同时包含两层内容:

  • exercises/:课程目标、概念和动手任务。
  • src/lessons/:已经完成的可执行课程实现。

快速开始

要求 Node.js >=22.19.0

npm install

真实 DeepSeek 课程需要项目根目录 .env

DEEPSEEK_API_KEY=your-key
# 可选,默认 deepseek-v4-flash
DEEPSEEK_MODEL_ID=deepseek-v4-flash

.env.example改成.env,替换成自己的 api_key

运行一个课程:

npm run lesson:agent
npm run lesson:tools
npm run lesson:architecture

验证项目:

npm run check

整体运行流程

普通命令行课程遵循同一条主链:

flowchart LR
  CLI["课程 CLI"] --> Config["runtime/deepseek"]
  Config --> Agent["Pi Agent"]
  Agent --> Provider["DeepSeek provider"]
  Agent --> Tools["课程工具"]
  Tools --> Transcript["toolResult / transcript"]
  Transcript --> Agent
  Agent --> Events["Agent events"]
  Events --> Output["终端观察输出"]
Loading

具体顺序:

  1. dotenv/config 加载本地环境变量。
  2. 课程解析 CLI 参数并选择模型。
  3. src/runtime/deepseek.ts 校验 key、从 Pi registry 解析模型并提供后端 key resolver。
  4. 课程创建 Agent,注入 system prompt、tools 和 hooks。
  5. agent.prompt() 启动 turn;Pi 把上下文转换为 provider request。
  6. 模型可直接回答,或产生 tool call。
  7. 工具执行结果成为 toolResult,进入 transcript 后触发下一 turn。
  8. AgentEvent 被课程观察器记录,用于理解 streaming、工具状态和最终 state。

课程 15 增加浏览器与 Fastify 链路:

flowchart LR
  Browser["Browser state"] -->|HTTP command| Fastify["Fastify adapter"]
  Fastify --> Session["SessionManager"]
  Session --> Runtime["AgentRuntime"]
  Runtime --> Agent["Pi Agent"]
  Agent --> DeepSeek["DeepSeek"]
  Agent --> Tool["Backend tools"]
  Agent --> Runtime
  Runtime --> Bus["EventEmitter EventBus"]
  Bus --> Adapter["BrowserEventProjector"]
  Bus --> History["SessionEventStore"]
  Adapter --> SSE["SSE listeners"]
  SSE --> Browser
Loading

Fastify 只处理 HTTP、schema 和 SSE;SessionManager 管理会话,AgentRuntime 封装 Pi Agent 与模型事务,EventEmitter 消息总线负责通知消费者。浏览器只接收经过投影的 JSON 事件,不接触 provider key 或原始 runtime state。

目录结构与模块职责

.
├── exercises/                 # 00–17 课程讲义与验收目标
├── scripts/                   # 本地包路径检查脚本
├── src/
│   ├── lessons/               # 每课的场景、工具、README;课程 15 含完整 Fastify 服务
│   ├── observability/         # 事件计数、压缩和终端增量输出
│   ├── runtime/               # provider 配置与通用消息构造
│   └── utils/                 # 基础打印与 Pi 输出展示
└── tests/                     # faux provider 与确定性模块测试

src/runtime/

deepseek.ts 是 DeepSeek 配置模块,负责:

  • 校验 DEEPSEEK_API_KEY
  • 解析并验证模型 id。
  • 提供只在后端使用的 key resolver。
  • 生成统一的模型摘要。

messages.ts 负责构造标准 user message,避免 session、workflow 和测试重复 provider message 结构。

src/observability/

agent-output.ts 放置不改变业务状态的观察 helper:assistant delta 输出、事件计数、连续事件压缩和文本截断。它只用于教学输出,不参与 Agent 决策。

src/lessons/15/

模块 功能与职责
agent/ AgentRuntime abstract interface、Pi Agent adapter 和工具。
session/ SessionManager abstract interface 与内存 session adapter。
messaging/ abstract event bus/store,以及基于 node:events 的 EventEmitter adapter。
consumer/ Browser event projector、前端 reducer 和 Fastify/SSE adapter。
bootstrap.ts 唯一 composition root,选择并连接所有具体 adapter。
start-server.ts 加载配置、监听 HOST/PORT、注册 SIGINT/SIGTERM 优雅退出。

这些 seam 让 Agent runtime、session、消息通知、浏览器协议和 HTTP transport 可以独立替换和测试。

src/lessons/

每个课程目录只保留与该课概念有关的实现:

  • executable 文件保持 load config -> await main() 的清晰顶层流程;
  • 课程工具放在同目录 *-tools.ts
  • 可复用策略单独成模块,例如 context-manager.tsmodel-router.ts
  • 课程 README 解释观察点和设计取舍。

tests/

测试尽量跨越与调用方相同的 interface,而不是检查实现内部:

  • context-manager.test.ts:上下文压缩与最近消息预算。
  • recovery-tool.test.ts:失败恢复和 operation-id 幂等。
  • model-routing.test.ts:fast/strong faux 模型的真实调用顺序。
  • frontend-backend-architecture.test.ts:session 隔离、浏览器事件、Fastify schema 与 key 零泄漏。

课程命令

命令 课程主题 Provider
npm run lesson:deepseek pi-ai 首次调用与 payload DeepSeek
npm run lesson:agent Agent 多轮基础 DeepSeek
npm run lesson:tools 工具定义与执行 DeepSeek
npm run lesson:debug events、state、abort DeepSeek
npm run lesson:context app messages 与 LLM context DeepSeek
npm run lesson:mini-research 复杂研究模式 DeepSeek
npm run lesson:memory memory 读取、候选与写入 DeepSeek
npm run lesson:policy tool policy、block 与审计 DeepSeek
npm run lesson:workflow search → read → synthesize DeepSeek
npm run lesson:compaction context budget 与摘要 DeepSeek
npm run lesson:recovery throw、continue 与幂等 Faux
npm run lesson:routing fast/strong 多模型路由 Faux
npm run lesson:architecture 启动课程 15 Fastify HTTP 服务 DeepSeek

完整学习顺序见 exercises/README.md,单课运行参数见对应 src/lessons/<number>/README.md

状态分层

项目刻意区分三类状态:

  1. Agent transcript:user、assistant、toolResult,用于模型继续推理与恢复。
  2. 浏览器显示状态:streaming draft、loading、tool panel、连接状态,可由事件重建。
  3. 应用 store:memory、source details、session metadata 和持久化 checkpoint。

transformContext 决定本轮 Agent 应该记住什么;convertToLlm 决定应用消息如何转成 provider 消息;浏览器协议决定哪些运行信息可以公开给 UI。这三处职责不要混合。

扩展新课程或模块

新增 executable lesson 时:

  1. src/lessons/<number>/ 创建入口和 README。
  2. 顶层只加载配置并 await main()
  3. 优先使用 src/runtime/src/observability/ 的共享能力。
  4. 课程专属工具和策略留在课程目录。
  5. 两个以上调用方需要相同行为时,再把它提升为共享模块。
  6. 使用 faux provider 测应用协议,真实 DeepSeek 只用于必要的集成冒烟。

安全与生产化提醒

  • provider key 只在后端 getApiKey resolver 中使用。
  • 浏览器 sessionId 必须配合用户鉴权,不能作为唯一访问凭证。
  • SSE 生产部署需要 event id、断点续传、背压和跨实例 session 路由。
  • 有副作用的工具使用 operation id 保证幂等。
  • 当前 session 和 event history 为内存实现;生产系统需要 TTL、持久化和容量上限。

About

Pi agent lessons

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages