拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

pi agent源码解读之StreamFn

pi agent源码解读之StreamFn

1. 先理解问题:Agent 核心为什么不应该绑定 Provider

一个 Agent 通常负责:

  1. 保存对话状态;
  2. 把用户消息加入上下文;
  3. 请求模型生成回复;
  4. 解析增量文本;
  5. 识别工具调用;
  6. 执行工具;
  7. 把工具结果追加回上下文;
  8. 继续下一轮模型请求。

其中第 3 步才真正涉及模型供应商:

Agent Loop │ ├─ 准备上下文 ├─ 调用模型生成回复 ← Provider 相关 ├─ 处理文本增量 ├─ 执行 Tool └─ 继续循环

如果 Agent 核心直接写:

import{streamAnthropic}from"...";import{streamOpenAI}from"...";

那么核心就会依赖具体 Provider,带来几个问题:

  • Agent 包必须安装所有 Provider SDK;
  • 增加新 Provider 时需要修改 Agent 核心;
  • 测试必须真正模拟或连接具体模型;
  • 用户无法方便地注入代理、缓存、重试、路由或本地模型;
  • Agent 核心与模型鉴权、HTTP、API 格式耦合。

Pi 的做法是把“请求模型并获得事件流”抽象成一个函数类型:StreamFn。


2.StreamFn是什么

定义位于:

packages/agent/src/types.ts:33

核心类型是:

exporttypeStreamFn=(model:Model<Api>,context:TranscriptContext,options?:SimpleStreamOptions,)=>AssistantMessageEventStream|Promise<AssistantMessageEventStream>;

可以把它理解为:

给我: - 一个模型描述 - 一份已经整理好的对话上下文 - 一些请求选项 返回: - 一个 AssistantMessageEventStream

它的职责非常明确:

StreamFn = 模型调用适配器

Agent 不关心这个函数内部是:

  • OpenAI Chat Completions;
  • Anthropic Messages;
  • Google Generative AI;
  • Azure;
  • Bedrock;
  • 本地 Ollama;
  • 远程代理;
  • 测试用 Mock;
  • 自己实现的 RPC 服务。

Agent 只依赖统一的返回类型:

AssistantMessageEventStream

3. Agent 核心如何注入streamFn

AgentOptions要求传入streamFn:

// packages/agent/src/agent.ts:113exportinterfaceAgentOptions{initialState?:AgentInitialState;convertToLlm?:(messages:AgentMessage[])=>Message[]|Promise<Message[]>;transformContext?:(...);streamFn:StreamFn;...}

构造 Agent 时:

constagent=newAgent({initialState:{model,},streamFn,});

Agent 会保存这个函数:

// packages/agent/src/agent.ts:194publicstreamFunction:StreamFn;

构造函数中完成注入:

// packages/agent/src/agent.ts:230this.streamFunction=runtimeOptions.streamFn??getDefaultStreamFn(
返回列表