找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2128

积分

0

好友

278

主题
发表于 2 小时前 | 查看: 2| 回复: 0

大家周一早。

最近在做 AI 项目的前端同学,一定遇到过这个痛点:老板说:“用户查天气的时候,AI 别干巴巴地说‘25度’,给我渲染一个带有动画的、能切换城市的天气卡片组件!”

以前我们怎么做?

  1. 强迫大模型输出特定格式的 JSON(比如{ "type": "weather", "temp": 25 })。
  2. 前端写一堆if-else去解析这个 JSON。
  3. 如果 JSON 没截断或者格式错了,前端直接白屏报错。

这种写法极其脆弱。而在 2026 年,借助于 React Server Components (RSC) 和 Vercel AI SDK,我们有了一种极其优雅的降维打击方案:Generative UI(生成式 UI)

今天,我们来看看到底什么是“让 AI 直接写 UI”。

01. 概念颠覆:什么是 Generative UI?

传统聊天

  • 用户:北京天气如何?
  • AI:String->“北京今天晴,25度。”-> 前端渲染。

生成式 UI

  • 用户:北京天气如何?
  • AI:Component->-> 前端直接渲染出可交互的组件

这意味着,聊天框不再是一个文本流,而是一个无限延伸的动态网页。用户可以直接在聊天记录里点击按钮、拖拽图表、甚至完成支付。

02. 核心原理:大模型凭什么懂组件?

大模型当然不懂 React,它只懂文字。

生成式 UI 的底层依然是 Function Calling(函数调用)。只不过我们把“工具执行的结果”换成了“一个 UI 组件”。

Vercel AI SDK 内部逻辑:

  1. 告诉 AI:“你有一个叫showWeather的工具,参数是city”。
  2. AI 决定调用showWeather({ city: 'Beijing' })
  3. 关键点来了:在服务端的工具执行完毕后,服务端不返回 JSON,而是直接返回一个序列化后的 React Server Component
  4. 前端收到组件,直接挂载渲染。

03. 实战:手写一个生成式天气卡片

我们使用 2026 年最主流的 Next.js App Router + Vercel AI SDK 来演示。

第一步:准备你的 UI 组件 (前端)

这是一个普通的 React 组件,带点 Tailwind 样式。

// components/WeatherCard.tsx
export function WeatherCard({ city, temp, condition }) {
  return (
    <div className="p-4 border rounded-xl bg-blue-50 shadow-sm w-64">
      <h2 className="text-xl font-bold">{city}</h2>
      <div className="flex justify-between items-center mt-2">
        <span className="text-3xl">{temp}°C</span>
        <span>{condition === ‘Sunny’ ? ‘☀️’ : ‘🌧️’}</span>
      </div>
      <button className="mt-4 text-sm text-blue-500">查看未来一周预报</button>
    </div>
  );
}

第二步:服务端定义 streamUI (全栈魔法)

当用户提问时,我们在服务端处理逻辑,并直接将组件 Stream 给前端

// actions.ts (Server Action)
‘use server’;

import { streamUI } from ‘ai’;
import { openai } from ‘@ai-sdk/openai’;
import { z } from ‘zod’;
import { WeatherCard } from ‘./components/WeatherCard’;

export async function askAI(question: string) {
  // 🌟 神奇的 streamUI 函数
  const result = await streamUI({
    model: openai(‘gpt-4o’),
    prompt: question,
    text: ({ content }) => <div>{content}</div>, // 普通文本对话
    tools: {
      // 告诉 AI 这个工具用来展示天气
      showWeather: {
        description: ‘获取指定城市的天气并展示 UI 卡片’,
        parameters: z.object({
          city: z.string(),
        }),
        // 🌟 核心:generate 函数直接返回一个 React 组件!
        generate: async function ({ city }) {
          // 模拟查数据库/API 获取真实数据
          const temp = Math.floor(Math.random() * 30);
          const condition = temp > 15 ? ‘Sunny’ : ‘Rainy’;

          // 直接返回刚才写的 UI 组件
          return <WeatherCard city={city} temp={temp} condition={condition} />;
        },
      },
    },
  });

  return result.value; // 返回流式 UI
}

第三步:前端页面展示

// page.tsx (Client Component)
‘use client’;

import { useState } from ‘react’;
import { askAI } from ‘./actions’;

export default function Chat() {
  const [messages, setMessages] = useState<React.ReactNode[]>([]);
  const [input, setInput] = useState(‘’);

  return (
    <div>
      {/* 渲染消息列表 (里面可能是文本,也可能是 WeatherCard 组件!) */}
      {messages.map((msg, i) => <div key={i}>{msg}</div>)}

      <form onSubmit={async (e) => {
        e.preventDefault();
        // 1. 把用户的问题 push 到列表 (这里用文本展示)
        setMessages(m => [...m, <div>{input}</div>]);

        // 2. 调用后端 Action
        const responseUI = await askAI(input);

        // 3. 把后端返回的 UI 组件直接 push 进列表!
        setMessages(m => [...m, responseUI]);
      }}>
        <input value={input} onChange={e => setInput(e.target.value)} />
        <button>发送</button>
      </form>
    </div>
  );
}

体验一下:
用户输入:“北京天气怎么样?”
屏幕上不会出现生硬的 Markdown 文本,而是直接凭空“刷”出了一个带有按钮、有温度、排版精美的卡片组件!

04. Vue 开发者怎么办?

细心的同学发现了,这套 streamUI 是严重依赖 React Server Components (RSC) 生态的。

那 Vue/Nuxt 开发者怎么玩 Generative UI?

目前社区的解法是:动态组件映射。让 AI 返回标准化的 JSON 结构(如{ component: “WeatherCard”, props: {...} }),前端维护一个组件注册表(Component Registry),利用 Vue 的 <component :is=“…”> 进行动态渲染。虽然没有 React 原生支持那么丝滑,但也能实现同样的用户体验。

结语

从“纯文本”到“结构化 JSON”,再到“可交互 UI”。Generative UI 彻底打破了我们对 Chatbot 的刻板印象。它让 AI 助理真正变成了一个个按需生成的“微型 App”。对于想深入探索更多前沿技术实现和案例的朋友,可以到云栈社区 的开发者论坛交流讨论。




上一篇:STEM像素阵列探测器(EMPAD):如何兼顾高动态范围与单电子灵敏度?
下一篇:OSPF三大表项详解:邻居表、LSDB、路由表与五种报文
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-10 12:23 , Processed in 0.524757 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表