RSC 与 streamUI(实验性)

官方现状: AI SDK RSC 目前是 experimental。生产环境请用 AI SDK UIuseChat + Route Handler)。从 RSC 迁到 UI 见官方 Migrating from RSC to UI

@ai-sdk/rsc 面向支持 React Server Components 的框架(主要是 Next.js App Router)。它让模型在服务端生成 React 组件,再流到客户端,而不是只流文本。这就是常说的 Generative UI。


和 AI SDK UI 的差别

AI SDK UI(推荐)AI SDK RSC(实验)
传输POST /api/chat + UI Message StreamServer Action + RSC payload
客户端useChat,自己渲染 parts直接插入服务端返回的 ReactNode
工具 UI前端根据 tool-* part 画工具的 generate 返回组件
稳定性生产默认可能随小版本破坏性变更

只有在「模型要决定渲染哪块卡片 / 图表」且团队能接受实验 API 时才用 RSC。普通聊天不要走这条路。


核心 API(知道名字即可)

函数作用
streamUI调模型,允许用 RSC 作答
createAI客户端-服务端 context,管 UI state / AI state
useUIState / useAIState类似 useState,分别管界面与模型上下文
useActions从客户端调用 Server Action
createStreamableUI / createStreamableValue手动推 UI 或可序列化值

安装:pnpm add @ai-sdk/rsc(另需 ai 与厂商包)。


streamUI 最小例子

工具形状接近 streamText,但执行函数叫 generate,必须返回 React 节点。可用 async generator:先 yield 加载态,再 return 最终组件。

app/actions.tsx

'use server';

import { streamUI } from '@ai-sdk/rsc';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';

export async function streamComponent() {
  const result = await streamUI({
    model: openai('gpt-5.1'), // 直连示例;Gateway 也可用字符串
    prompt: 'Get the weather for San Francisco',
    text: ({ content }) => <div>{content}</div>,
    tools: {
      getWeather: {
        description: 'Get the weather for a location',
        inputSchema: z.object({ location: z.string() }),
        generate: async function* ({ location }) {
          yield <div>getting weather...</div>;
          const weather = '82°F';
          return (
            <div>
              The weather in {location} is {weather}
            </div>
          );
        },
      },
    },
  });

  return result.value;
}

没有合适工具时,模型走 text,你仍要返回一个组件。streamUI 的返回值必须是 React 节点。

客户端页调用 Server Action(普通 async 函数):

'use client';

import { useState } from 'react';
import { streamComponent } from './actions';

export default function Page() {
  const [component, setComponent] = useState<React.ReactNode>();

  return (
    <form
      onSubmit={async (e) => {
        e.preventDefault();
        setComponent(await streamComponent());
      }}
    >
      <button type="submit">Stream Component</button>
      <div>{component}</div>
    </form>
  );
}

实践建议

  • 密钥仍只留在 Server Action 里,和 Route Handler 同一纪律。
  • 多轮聊天需要 createAI 同步 AI state 与 UI state;比 useChat 重,官方模板(Gemini Chatbot、Generative UI with RSC)可参考,不要从零发明状态机。
  • HarnessAgent / 普通 streamText 聊天 不要streamUI 混在同一个路由里硬接。

学完概念后,把时间投回 useChat工具调用。需要卡片式 UI 时,也可以在 UI 路径里用 tool-* part 渲染组件,不必上 RSC。


下一步

评论