双层流架构(vercel/ai)
vercel/ai 中存在两套独立的流式类型系统:Provider 层流(LanguageModelV4StreamPart,21 种事件,Provider↔框架层)和应用层流(TextStreamPart,框架层↔应用层),框架层在中间做聚合与转换,两层各有自己的 tool-approval 类型。
架构图
text
Provider(doStream)
↓ LanguageModelV4StreamPart(21 种事件)
框架层(generate-text.ts)
↓ 聚合转换
应用层(useChat / streamText 消费者)
↓ TextStreamPart(应用层事件集)
两层流的类型系统对比
| 层次 | 类型名 | 位置 | 职责 |
|---|---|---|---|
| Provider 层流 | LanguageModelV4StreamPart | @ai-sdk/provider | 定义 Provider 能发出的所有事件,是底层协议规范 |
| 应用层流 | TextStreamPart | packages/ai/src/ | 定义应用消费者看到的流式数据,更高层的抽象 |
框架层(generate-text.ts / stream-language-model-call.ts)在两层之间做:
- 聚合:把 start/delta/end 三元组合并成完整内容
- 类型转换:
LanguageModelV4StreamPart→TextStreamPart - 注入:callId、stepNumber、performance 等框架层数据
tool-approval 在两层的对称性
看起来 tool-approval-response 在 Provider 协议里缺失,实际上它以不同名字存在于应用层:
- Provider 层:
LanguageModelV4ToolApprovalRequest— Provider 发出审批请求(下行) - 应用层:
TextStreamToolApprovalResponsePart— 应用层回传审批结果(上行)
两条路不在同一层,但合在一起构成完整的审批闭环:
- Provider →
tool-approval-request→ 框架层收集 - 用户输入 → 框架层组装 →
TextStreamToolApprovalResponsePart→ 应用层 - 审批结果在下次
doGenerate/doStream调用时作为 prompt 传回 Provider
为什么要两层
- Provider 层极薄,不关心应用业务逻辑
- 应用层包含更丰富的上下文(callId、性能数据、用户友好的格式)
- 框架层是转换器,让 Provider 实现者只需关心协议,让应用开发者只需关心高层 API
关联知识
- [[languagemodelv4streampart]] — Provider 层流的完整类型定义
- [[stopcondition]] — 框架层控制循环终止的机制,与双层流架构配合工作