← [ BACK_TO_NOTES ]

Vercel AI SDK 聊天运行时模式

解释如何把 AI SDK UI 的客户端会话状态与 AI SDK Core 的流式生成组合成聊天运行时模式;不承担 SDK 产品资源索引。

#concept #evergreen #frontend #ai

[!info] related notes

Vercel AI SDK 聊天运行时模式

本页是“如何组合聊天运行时”的工程概念页,不是 Vercel AI SDK 产品/资源页;产品能力与入口统一由 Vercel AI SDK UI 承担。

角色边界

  • Vercel AI SDK UI:产品/SDK 资源页,回答“这个 SDK 是什么、有哪些入口与能力”。
  • 本页:运行时组合模式,回答“客户端会话状态、服务端流式生成和工具调用如何拼成一条聊天链路”。
  • Chat UI:更通用的对话界面概念,不依赖 Vercel AI SDK。

核心组件

组件职责
streamText后端:调用 LLM 并流式返回
useChat前端:管理消息状态、发送、流式接收
toDataStreamResponse后端:将流转为标准 Response
tool定义工具 schema 和执行函数

后端 API Route

// app/api/chat/route.ts
import { openai } from "@ai-sdk/openai";
import { streamText, tool } from "ai";
import { z } from "zod";

export async function POST(req: Request) {
  const { messages, system } = await req.json();

  const result = streamText({
    model: openai("gpt-4o"),
    system: "你是一个专业的健康助手。",
    messages,
    maxSteps: 5,  // 允许多轮工具调用
    tools: {
      getWeather: tool({
        description: "获取指定城市的天气",
        parameters: z.object({
          city: z.string().describe("城市名称"),
        }),
        execute: async ({ city }) => {
          const weather = await fetchWeather(city);
          return weather;
        },
      }),
    },
  });

  return result.toDataStreamResponse();
}

前端 useChat

// app/chat/page.tsx
"use client";
import { useChat } from "ai/react";

function ChatPage() {
  const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
    api: "/api/chat",
    maxSteps: 5,  // 与后端一致
  });

  return (
    <div className="flex flex-col h-screen">
      <div className="flex-1 overflow-y-auto p-4 space-y-4">
        {messages.map((m) => (
          <div key={m.id} className={m.role === "user" ? "text-right" : ""}>
            <div className="inline-block rounded-xl p-3 max-w-[80%]">
              {m.content}
            </div>
            {/* 工具调用展示 */}
            {m.toolInvocations?.map((t) => (
              <div key={t.toolCallId} className="text-sm text-muted-foreground">
                🔧 {t.toolName}: {JSON.stringify(t.args)}
              </div>
            ))}
          </div>
        ))}
      </div>
      <form onSubmit={handleSubmit} className="p-4 border-t flex gap-2">
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="输入消息..."
          className="flex-1 rounded-xl border p-3"
        />
        <button type="submit" disabled={isLoading}>发送</button>
      </form>
    </div>
  );
}

与 assistant-ui 集成

// 使用 assistant-ui 的 useChatRuntime 桥接
import { useChatRuntime } from "@assistant-ui/react-ai-sdk";

function AssistantUIChat() {
  const runtime = useChatRuntime({
    api: "/api/chat",
    maxSteps: 5,
  });

  return (
    <AssistantRuntimeProvider runtime={runtime}>
      <Thread />  {/* assistant-ui 预构建组件 */}
    </AssistantRuntimeProvider>
  );
}

useChatRuntime 内部调用 useChat,将返回的状态映射到 assistant-ui 的 Runtime 接口。

多模型支持

// 不同模型只需换 provider
import { openai } from "@ai-sdk/openai";
import { anthropic } from "@ai-sdk/anthropic";
import { google } from "@ai-sdk/google";

const result = streamText({
  model: openai("gpt-4o"),        // OpenAI
  // model: anthropic("claude-sonnet-4-20250514"),  // Anthropic
  // model: google("gemini-2.0-flash"),  // Google
  messages,
});

工具调用流式累积

// 流式接收工具调用时,参数是逐步累积的
// message.toolInvocations[].state 变化:
// "call" → 部分参数
// "result" → 完整结果

const result = streamText({
  model: openai("gpt-4o"),
  messages,
  tools: {
    extractInfo: tool({
      parameters: z.object({
        bodyPart: z.string(),
        symptomType: z.string(),
      }),
      execute: async (args) => {
        // args 在 state="result" 时才完整
        return processSymptom(args);
      },
    }),
  },
});

优雅之处:

  • streamText + toDataStreamResponse 一行完成流式 API Route
  • maxSteps 自动处理多轮工具调用循环,无需手动编排
  • zod schema 同时用于类型推断和运行时验证
  • 从 useChat 迁移到 useChatRuntime 零成本——底层是同一个 hook

学习检查

  1. 为什么 useChat 本身不足以定义完整的聊天运行时?
  2. 客户端状态与服务端流式生成之间最关键的契约是什么?
  3. 什么时候应该查 SDK 资源页,而不是查本运行时模式页?
  4. 如果替换底层模型 Provider,这条运行时边界中哪些部分应保持不变?

创建于 2026/6/25 更新于 2026/10/1
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本