AI SDK 消息分层架构解析:从 UI 消息到 Provider 私有请求的四层消息体系 📅 发布时间:2026/9/10 18:37:10 👁 浏览次数: AI SDK 消息分层架构解析从 UI 消息到 Provider 私有请求的四层消息体系【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/aiAI SDKThe AI Toolkit for TypeScript在同一个对话从浏览器一路走到模型 API 的完整链路上定义了四层消息表示UI 消息UI Messages、模型消息Model Messages、语言模型消息Language Model Messages与 Provider 私有消息Provider-specific Messages。本文以仓库中的 message-layers.md 为骨架结合 packages/ai、packages/provider-utils 与 packages/provider 的源码逐层剖析每一层消息的定位、类型结构与转换职责帮助你理解 AI SDK 为何要设计这套分层体系以及在开发多 Provider 应用时如何正确使用它们。为什么需要四层消息架构一个典型的 AI 应用请求会经历这样的旅程用户在 React/Vue/Svelte 前端输入消息前端把它交给useChat等 UI 状态管理服务端拿到后用generateText/streamText组织 prompt核心 SDK 把用户友好的 prompt 翻译成标准化的语言模型调用最终由 Provider 包如ai-sdk/openai把标准请求转换成 OpenAI、Anthropic 等厂商的专属 HTTP 请求体。如果全程只用一种消息格式就会出现两个难以调和的矛盾UI 层需要富信息要渲染文本、推理过程、工具调用、文件、来源引用、流式状态甚至 Provider 自定义内容这些信息对模型 API 而言是噪音Provider 层需要准信息各家 API 对角色、内容分部、工具结果的组织方式千差万别必须有一个稳定中间格式让所有 Provider 共享。因此 AI SDK 把消息拆成四层每层只对相邻层负责层与层之间通过显式的转换函数衔接实现了前端渲染与厂商适配的解耦。从源码结构看这四层恰好对应三个包packages/ai面向应用、packages/provider-utils面向 SDK 内部与工具、packages/provider面向 Provider 实现。第一层UI 消息UI Messages——为渲染而生UI 消息定义在 packages/ai/src/ui/ui-messages.ts是客户端与 API 路由之间、以及前端组件渲染时使用的消息格式。它的核心设计是一切皆 Part一条UIMessage不再是一个字符串而是一个携带parts数组的结构化对象。export interface UIMessageMETADATA, DATA_PARTS, TOOLS { id: string; role: system | user | assistant; metadata?: METADATA; parts: ArrayUIMessagePartDATA_PARTS, TOOLS; }UIMessagePart是多种 Part 的联合类型每种 Part 用type字段区分Part 类型用途text普通文本带state: streaming \| done用于流式渲染customProvider 自定义内容kind格式为{provider}.{provider-type}reasoning推理过程文本如思维链同样有流式状态source-url/source-document引用来源URL 或文档用于 RAG 场景展示file用户上传或模型生成的文件含mediaType、url、可选providerReferencereasoning-file推理过程中生成的文件step-start多步 Agent 流程中的步骤边界标记data-{name}自定义数据 PartisDataUIPart通过part.type.startsWith(data-)判断tool-{name}/dynamic-tool工具调用渲染信息UI 层最具特色的是工具 Part 的状态机设计。UIToolInvocation通过state字段完整刻画了一次工具调用的生命周期input-streaming输入参数流式到达→input-available参数齐备→output-available执行成功返回结果→output-error执行出错含errorText此外还支持approval-requested/approval-responded/output-denied三种人工审批状态对应 AI SDK 的工具审批human-in-the-loop能力。工具 Part 分为两种静态工具ToolUIPart工具的输入输出类型在开发期已知Part 类型被编码为tool-{toolName}通过getStaticToolName从type中解析出工具名动态工具DynamicToolUIPart输入输出类型未知工具名放在toolName字段用getToolName统一获取。UI 消息还提供了一组类型守卫isTextUIPart、isToolUIPart、isFileUIPart、isReasoningUIPart等供渲染组件安全地做类型收窄。这套结构让useChat的返回结果可以直接交给任意前端框架渲染而无需关心底层模型 API 的差异。第二层模型消息Model Messages——开发者友好的统一入口模型消息定义在 packages/provider-utils/src/types/model-message.ts是应用开发者直接书写的消息格式用于generateText/streamText等方法的messages字段。export type ModelMessage | SystemModelMessage | UserModelMessage | AssistantModelMessage | ToolModelMessage;四种角色分别在独立文件中定义system-model-message.ts{ role: system, content: string }源码注释特别强调优先使用 prompt 的 system 字段而非 system 消息以增强对提示注入攻击的抵抗力部分 Provider 也不支持多条 system 消息user-model-message.tscontent可以是纯字符串也可以是ArrayTextPart | ImagePart | FilePart即支持多模态输入assistant-model-message.tscontent为字符串或 Part 数组Part 类型比用户消息更丰富包含ReasoningPart、ReasoningFilePart、ToolCallPart、ToolResultPart以及ToolApprovalRequest工具审批请求tool-model-message.tscontent为ArrayToolResultPart | ToolApprovalResponse专门回传工具执行结果。这一层的关键价值在于开发体验开发者不需要了解各家 API 的差异只需遵循这套统一的、贴近直觉的消息结构。所有消息都携带可选的providerOptions透传字段用于把 Provider 专属能力如 OpenAI 的store、Anthropic 的缓存控制直接传递下去。content-part.ts 定义了共享的 Part 类型其中FilePart支持四种数据形态data原始字节 /url/referenceProvider 文件引用 /text内联文本mediaType既可填完整 IANA 类型如image/png也可只填顶级段如image。值得留意的是源码中ImagePart以及file-data、image-url等若干历史 Part 均标注了deprecated推荐统一迁移到带mediaType的FilePart这正是本仓库当前版本的消息演进方向。第三层语言模型消息Language Model Messages——稳定不变的标准化规范语言模型消息定义在 packages/provider/src/language-model/v4/language-model-v4-prompt.ts。源码注释明确指出这不是面向用户的 promptAI SDK 方法会把用户友好的 prompt 类型如 chat prompt、instruction prompt映射到这个格式。LanguageModelV4Prompt是ArrayLanguageModelV4Message每条消息同样是角色驱动的system内容为纯字符串userArrayTextPart | FilePartassistantArrayTextPart | FilePart | CustomPart | ReasoningPart | ReasoningFilePart | ToolCallPart | ToolResultParttoolArrayToolResultPart | ToolApprovalResponsePart。与第二层相比这一层的差异体现了标准化的取舍维度模型消息第二层语言模型消息第三层定位用户友好的 DX 格式稳定、标准化的规范格式FilePart数据形态支持data/url/reference/text四种同样支持四种见SharedV4FileData角色system/user/assistant/tool相同设计目标方便书写便于跨 Provider 长期稳定这一层的 Part 定义得极为严谨LanguageModelV4ToolCallPart带toolCallId用于与结果配对providerExecuted标记工具是否由 Provider 端执行为 false 时由客户端执行LanguageModelV4ToolResultOutput是一组带类型的判别联合包括text、json、execution-denied用户拒绝执行、error-text、error-json以及可携带文件与自定义内容的content形态——这让 Provider 既能原样转发文本/JSON也能结构化表达错误与多模态结果。每个 Part 都统一支持providerOptions透传使 Provider 专属行为可以完全封装在 Provider 内部。之所以单独设立这一层从架构上可以推断它充当Provider 实现的公共契约。所有 Provider 包openai、anthropic、google、mistral 等都实现同一套LanguageModelV4Prompt输入SDK 核心只需做一次从模型消息到语言模型消息的转换而不是为每个厂商各写一套转换逻辑同时该规范刻意保持稳定避免模型消息层因 DX 演进如新增 Part 类型而连带破坏所有 Provider 的实现。第四层Provider 私有消息Provider-specific Messages——最终的 API 请求体最后一层发生在每个 Provider 包内部把标准化的LanguageModelV4Prompt转换成厂商 API 要求的最终请求格式。原文档以 OpenAI 为例指出关键实现位于OpenAIResponsesLanguageModel的getArgs()与doGenerate()方法——即 packages/openai/src/responses/openai-responses-language-model.ts。从源码可以确认其调用链第 732-774 行getArgs(options)内部调用静态方法prepareRequest把LanguageModelV4CallOptions包含prompt: LanguageModelV4Prompt、模型 ID、配置等编译成 OpenAI Responses API 的请求体body并产出warnings、toolNameMapping、providerOptionsName等辅助信息doGenerate(options)拿到args后先从 prompt 中提取审批请求 ID → 工具调用 ID的映射extractApprovalRequestIdToToolCallIdMapping用于人工审批流程通过postJsonToApi把bodyPOST 到config.url({ path: /responses, modelId })再用openaiResponsesResponseSchema解析响应。这一层完全属于 Provider 的内部实现细节OpenAIResponsesLanguageModel需要处理 OpenAI 特有的消息结构如input数组、tools定义、store选项、parallel_tool_calls等而 Anthropic 的实现则会映射成messagessystemtools的 Claude API 结构。正因为前两层的统一抽象这些厂商差异被牢牢关在第四层内SDK 上层完全无感知。其他 Provider 包如 packages/anthropic/src、packages/google/src也都遵循同一模式实现LanguageModelV4接口、接收LanguageModelV4Prompt、在doGenerate/doStream中完成厂商格式转换。这是本仓库所有 Provider 共享的统一架构约定。四层消息的流转全貌把四层串起来一次请求的完整消息旅程是UI 消息 (packages/ai/src/ui/ui-messages.ts) │ useChat / 前端渲染、前后端传输 ▼ 模型消息 (packages/provider-utils/src/types/model-message.ts) │ 开发者书写 messages 字段generateText / streamText ▼ 语言模型消息 (packages/provider/src/language-model/v4/language-model-v4-prompt.ts) │ SDK 核心标准化转换Provider 公共契约 ▼ Provider 私有消息 (如 packages/openai/src/responses/openai-responses-language-model.ts) 厂商 API 请求体POST /responses 等理解这套分层对你的实际开发有三点直接帮助写应用时只用模型消息在generateText/streamText的messages里按角色书写即可多模态文件用FilePart注意优先使用未废弃的file形态工具调用结果放进tool角色的ToolResultPart做渲染时只用 UI 消息前端用useChat拿到UIMessage[]利用parts的类型守卫isTextUIPart、isToolUIPart等分派渲染state字段直接驱动流式动画与工具调用状态机写 Provider 时只用语言模型消息如果你要接入一个新模型厂商实现LanguageModelV4接口、消费LanguageModelV4Prompt在doGenerate/doStream里做最后一次厂商格式转换即可无需关心上层消息形态。四层消息体系把用户体验第一层、开发体验第二层、规范稳定性第三层与厂商适配第四层四种诉求拆解到各自独立的边界内正是 AI SDK 能够横跨几十家模型厂商而保持 API 一致性的架构基石。想深入探究某一层的细节可以直接阅读上述对应源码文件UI Part 全量与类型守卫见 ui-messages.ts消息内容 Part 定义见 content-part.ts标准 prompt 规范见 language-model-v4-prompt.tsProvider 转换示例见 openai-responses-language-model.ts。【免费下载链接】aiThe AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and agents项目地址: https://gitcode.com/GitHub_Trending/ai/ai创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考