長話短說

在本教程中,您將了解什麼是生成式 UI 以及如何使用它在應用程式中提供動態使用者體驗。

您還將學習如何建立互動式銷售儀表板,讓您可以使用 AI 副駕駛加入、更新和刪除資料。

本實用指南將介紹前端和人工智慧應用程式開發的最新前沿。您的用戶將會感激您磨練了這些技能。

圖片說明


CopilotKit:建構應用內人工智慧副駕駛的框架

CopilotKit是一個開源的AI副駕駛平台。我們可以輕鬆地將強大的人工智慧整合到您的 React 應用程式中。

建造:

  • ChatBot:上下文感知的應用內聊天機器人,可以在應用程式內執行操作 💬

  • CopilotTextArea:人工智慧驅動的文字字段,具有上下文感知自動完成和插入功能📝

  • 聯合代理:應用程式內人工智慧代理,可以與您的應用程式和使用者互動🤖

圖片說明

{% cta https://git.new/devtoarticle1 %} Star CopilotKit ⭐️ {% endcta %}


什麼是生成式使用者介面?

生成式UI是指根據使用者輸入動態產生並即時更新的UI元件。人工智慧嵌入式軟體應用程式會聽取使用者的提示,並根據給定的指令產生使用者介面。 CopilotKit 使用此功能使用戶能夠在副駕駛聊天視窗中渲染 React 元件。

先決條件

要完全理解本教程,您需要對 React 或 Next.js 有基本的了解。

我們還將使用以下工具:

  • CopilotKit - 一個開源副駕駛框架,用於建立自訂 AI 聊天機器人、應用程式內 AI 代理程式和文字區域。

  • OpenAI API 金鑰- 提供 API 金鑰,使我們能夠使用 ChatGPT 模型執行各種任務。

  • Shadcn/ui - 可自訂和可重複使用的 UI 元件的集合。

  • Recharts - 專為 React 應用程式建置的圖表庫

使用 CopilotKit 產生 UI


專案設定和套件安裝

首先,透過在終端機中執行以下程式碼片段來建立 Next.js 應用程式:

npx create-next-app generative-ui-with-copilotkit

安裝 CopilotKit 軟體套件。這些套件使 AI copilot 能夠從 React 狀態檢索資料並在應用程式中做出決策。

npm install @copilotkit/react-ui @copilotkit/react-core @copilotkit/backend recharts

透過執行以下程式碼片段在 ext.js 專案中設定shadcn/ui

npx shadcn-ui@latest init

透過回答以下安裝問題來設定components.json檔案:

Which style would you like to use? › Default
Which color would you like to use as base color? › Slate
Do you want to use CSS variables for colors? › > yes

恭喜!現在,您的 Next.js 專案中應該有一個components.json文件,該文件概述了 Shadcn UI 的配置以及將包含各種 UI 元件的components資料夾。

最後,將應用程式中使用的以下 ShadCn 元件新增至應用程式: CardChartCheckboxTable元件。

npx shadcn-ui@latest add card
npx shadcn-ui@latest add chart
npx shadcn-ui@latest add checkbox
npx shadcn-ui@latest add table

使用 Next.js 建立銷售儀表板

在本部分中,您將了解如何使用 ShadCn UI 元件建立視覺化資料的銷售儀表板。

銷售儀表板概述

首先,在 Next.js 專案的根目錄下建立一個types.d.ts文件,並將以下程式碼片段複製到該文件中:

interface Todo {
    id: number;
    text: string;
    completed: boolean;
}
interface Invoice {
    id: number;
    status: "Paid" | "Pending" | "Overdue";
    amount: number;
    method: "Credit Card" | "Paypal" | "Bank Transfer";
}
interface Chart {
    month: string;
    sales: number;
    customers: number;
}

上面的程式碼片段定義了應用程式中使用的各種變數的資料結構。

在 Next.js 應用程式資料夾中新增components資料夾,並建立應用程式、卡片、圖表、核取方塊、導覽和表格元件。

cd app
mkdir components && cd components
touch App.tsx Card.tsx Chart.tsx Checkbox.tsx Nav.tsx Table.tsx

更新App.tsx元件以包含必要的 React 狀態和函數:

import { useState } from "react";
import ChartComponent from "@/app/components/Chart";
import CardComponent from "@/app/components/Card";
import TableComponent from "@/app/components/Table";
import CheckboxComponent from "@/app/components/Checkbox";
import NavComponent from "@/app/components/Nav";

export default function App() {
    //👇🏻 a todo list
    const [todoList, setTodoList] = useState<Todo[]>([
        {
            id: 1,
            text: "Learn about CopilotKit implementation",
            completed: false,
        },
        {
            id: 2,
            text: "Remind Uli about the next project",
            completed: false,
        },
        {
            id: 3,
            text: "Send an invoice to CopilotKit team",
            completed: false,
        },
    ]);

    //👇🏻 an invoice list
    const [invoiceList, setInvoiceList] = useState<Invoice[]>([
        {
            id: 1,
            status: "Pending",
            amount: 1000,
            method: "Credit Card",
        },
        {
            id: 2,
            status: "Paid",
            amount: 2000,
            method: "Paypal",
        },
        {
            id: 3,
            status: "Overdue",
            amount: 3000,
            method: "Bank Transfer",
        },
    ]);

  //👇🏻 the chart data
    const [chartData, setChartData] = useState<Chart[]>([
        { month: "January", sales: 350, customers: 80 },
        { month: "February", sales: 200, customers: 30 },
        { month: "March", sales: 1500, customers: 120 },
        { month: "April", sales: 1050, customers: 190 },
        { month: "May", sales: 1200, customers: 130 },
        { month: "June", sales: 550, customers: 140 },
        { month: "July", sales: 1200, customers: 130 },
    ]);

    //👇🏻 calculates the total sales and number of customers
    const calculateTotal = (key: keyof Chart): number => {
        if (key === "sales")
            return chartData.reduce((acc, item) => acc + item.sales, 0);
        return chartData.reduce((acc, item) => acc + item.customers, 0);
    };

    return (/**-- 👉🏻 UI components 👈🏼 ---*/)
}

從 App 元件渲染以下 UI 元件,每個元件都設計用於顯示發票、待辦事項和銷售資料。

export default function App() {
    //👉🏻 the states and functions

    return (
        <main>
            <NavComponent />
            <div className='w-full flex items-center justify-between p-4 md:flex-row space-x-4'>
                <div className='lg:w-1/2 h-[300px] lg:mb-0 mb-4 w-full'>
                    <CardComponent
                        invoiceLength={invoiceList.length}
                        todoLength={todoList.length}
                        totalCustomers={calculateTotal("customers")}
                        totalSales={calculateTotal("sales")}
                    />
                </div>
                <div className='lg:w-1/2  h-[300px] w-full lg:mb-0 mb-4 '>
                    <ChartComponent chartData={chartData} />
                </div>
            </div>
            <div className='w-full flex flex-row items-center justify-between lg:space-x-4 p-4'>
                <div className='lg:w-1/2 w-full h-full lg:mb-0 mb-8'>
                    <TableComponent invoiceList={invoiceList} />
                </div>
                <div className='lg:w-1/2 w-full h-full lg:mb-0 mb-4'>
                    <CheckboxComponent todoList={todoList} setTodoList={setTodoList} />
                </div>
            </div>
        </main>
    );
}

最後,您可以從GitHub 儲存庫複製各種儀表板元件。


如何將 CopilotKit 新增至 Next.js 應用程式

在本部分中,您將了解如何將 CopilotKit 新增至應用程式,以使用戶能夠使用 AI copilot 自動新增、刪除和更新資料。

在繼續之前,請造訪OpenAI 開發者平台並建立一個新的金鑰。

OpenAI API 金鑰

建立一個.env.local檔案並將新建立的金鑰複製到該檔案中。

OPENAI_API_KEY=<YOUR_OPENAI_SECRET_KEY>
OPENAI_MODEL=gpt-4-1106-preview

接下來,您需要為 CopilotKit 建立 API 端點。在 Next.js 應用程式資料夾中,建立一個包含route.ts檔案的api/copilotkit資料夾。

cd app
mkdir api && cd api
mkdir copilotkit && cd copilotkit
touch route.ts

將下面的程式碼片段複製到route.ts檔中。 CopilotKit 後端接受使用者的請求並使用 OpenAI 模型做出決策。

import { CopilotRuntime, OpenAIAdapter } from "@copilotkit/backend";

export const runtime = "edge";

export async function POST(req: Request): Promise<Response> {
    const copilotKit = new CopilotRuntime({});
    const openaiModel = process.env["OPENAI_MODEL"];
    return copilotKit.response(req, new OpenAIAdapter({ model: openaiModel }));
}

若要將應用程式連接到後端 API 路由,請將下面的程式碼片段複製到app/page.tsx檔案中。

"use client"
import { CopilotKit } from "@copilotkit/react-core";
import { CopilotPopup } from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";
import "@copilotkit/react-textarea/styles.css";
import App from "./components/App";

export default function Home() {
    return (
        <CopilotKit runtimeUrl='/api/copilotkit/'>
            <App />
            <CopilotPopup
                instructions='Help the user update and manipulate data on the chart, table, todo, and card components.'
                defaultOpen={true}
                labels={{
                    title: "Data Visualization Copilot",
                    initial:
                        "Hello there! I can help you add, edit, and remove data from the various components on the page. You can update the chat, table, and todo list. Let's get started!",
                }}
                clickOutsideToClose={false}
            ></CopilotPopup>
        </CopilotKit>
    );
}

CopilotKit 元件包裝整個應用程式並接受包含 API 端點連結的runtimeUrl屬性。 CopilotKitPopup元件為應用程式加入了一個聊天機器人側邊欄面板,使我們能夠使用 AI 副駕駛提供各種指令並執行各種操作。

CopilotKit 儀表板應用程式概述


利用生成式 UI 和 CopilotKit 進行互動操作

CopilotKit 提供了兩個鉤子,使我們能夠處理使用者的請求並插入應用程式狀態: useCopilotActionuseCopilotReadable

useCopilotAction掛鉤可讓您定義 CopilotKit 執行的動作。它接受包含以下參數的物件:

  • name - 操作的名稱。

  • 描述 - 操作的描述。

  • 參數 - 包含所需參數清單的陣列。

  • render - 傳回 UI 元件的字串或函數。

  • handler - 由操作觸發的可執行函數。

useCopilotAction({
    name: "sayHello",
    description: "Say hello to someone.",
    parameters: [
        {
            name: "name",
            type: "string",
            description: "name of the person to say greet",
        },
    ],
    render: "Process greeting message...",
    handler: async ({ name }) => {
        alert(`Hello, ${name}!`);
    },
});

render屬性可讓我們根據使用者輸入和操作的目前狀態動態顯示 React 元件,從而方便使用CopilotKit 產生 UI 。您很快就會了解如何實現此功能。

useCopilotReadable掛鉤向 CopilotKit 提供應用程式狀態。

import { useCopilotReadable } from "@copilotkit/react-core";

const myAppState = "...";
useCopilotReadable({
  description: "The current state of the app",
  value: myAppState
});

現在,讓我們將應用程式狀態插入到 CopilotKit 中。

App.tsx元件中,將chartDatainvoiceListtodoList狀態傳遞到 CopilotKit 中。

   //👇🏻 pass Chart data to CopilotKit
    useCopilotReadable({
        description:
            "The chart data is a list of sales and customers data for each month. You can update the data for each month. It contains the month, sales, and customers data.",
        value: chartData,
    });

 //👇🏻 pass invoice data to CopilotKit
    useCopilotReadable({
        description: "The invoice list is a list of invoices that need to be paid. You can add, edit, and remove invoices from the list and also update the status of the invoice. An invoice status can either be Paid, Pending, or Overdue. The acceptable payment methods are Credit Card, Paypal, and Bank Transfer.",
        value: invoiceList,
    });

 //👇🏻 pass todolist data to CopilotKit
    useCopilotReadable({
        description: "The todo list is a list of tasks that need to be completed. You can add, edit, and remove tasks from the list.",
        value: todoList,
    });

使用 CopilotKit 自動執行各種操作

我們需要允許用戶在應用程式中建立、更新和刪除資料。因此,讓我們使用useCopilotAction掛鉤來建立執行以下操作的動作:

  • 更新圖表資料,

  • 建立新發票,

  • 刪除發票,

  • 更新待辦事項狀態,

  • 建立新的待辦事項,

  • 全部刪除。

新增一個將chartData更新到App.tsx檔案的操作:

   //👇🏻 action to update chartData
    useCopilotAction({
        name: "updateChartData",
        description: "Update the chart data for the a particular month.",
        parameters: [
            {
                name: "month",
                type: "string",
                description: "The month to update the data for.",
                required: true,
            },
            {
                name: "sales",
                type: "number",
                description: "The sales data for the month.",
                required: true,
            },
            {
                name: "customers",
                type: "number",
                description: "The customers data for the month.",
                required: true,
            },
        ],
        render: ({ status, args }) => {
            const { month, sales, customers } = args;
            if (month === undefined || sales === undefined || customers === undefined) return "";
            if (typeof month !== "string" || typeof sales !== "number" || typeof customers !== "number") return "";

            const updateChart = () => {
                setChartData((prev)  => {
                    return prev.map((item) => {
                        if (item.month === month) {
                            return { month, sales, customers };
                        }
                        return item;
                    });
                });
            };
            return (
                <div className="w-full p-2">
                    <p className="text-sm text-blue-400 mb-2">Status: {status}</p>
                    <ChartComponent chartData={[{month, sales, customers}]} />
                    <button className="px-4 py-2 bg-blue-400 text-white shadow rounded-md" onClick={updateChart}>Update</button>
                </div>
            )
        },
        handler: async () => {
            // Do nothing
        },
    });
  • 從上面的程式碼片段來看,

  • 此操作接受描述chartData React 狀態屬性的參數陣列。

  • render屬性顯示使用者提示的結果以及允許使用者將資料新增至頁面的按鈕。

使用 CopilotKit 產生 UI

接下來,建立從應用程式建立和刪除發票的操作。

//👇🏻 action to add new invoice
    useCopilotAction({
        name: "addNewInvoice",
        description: "Add new invoices to the invoice list",
            parameters: [
                {
                    name: "status",
                    type: "string",
                    description: "The status of the invoice.",
                    required: true,
                },
                {
                    name: "amount",
                    type: "number",
                    description: "The amount of the invoice.",
                    required: true,
                },
                {
                    name: "method",
                    type: "string",
                    description: "The payment method of the invoice.",
                    required: true,
                },
        ],
        render: ({ status: fetchStatus, args }) => {
            const { amount, method, status } = args;
            if (method !== "Credit Card" && method !== "Paypal" && method !== "Bank Transfer") return "";
            if (status !== "Paid" && status !== "Pending" && status !== "Overdue") return "";
            if (amount === undefined) return "";

            const addInvoice = () => {
                 setInvoiceList((prev ) => {
                    return [...prev, { id: prev.length + 1, status, amount, method }];
                });
            };
            return (
                <div className="w-full p-2">
                    <p className="text-sm text-blue-400 mb-2">Status: {fetchStatus}</p>
                    {status && amount !== undefined && method && <TableComponent invoiceList={[{ id: invoiceList.length + 1, status, amount, method }]} />}
                    <button className="px-4 py-2 bg-blue-400 text-white shadow rounded-md" onClick={addInvoice}>Add to Page</button>
                </div>
            )
         },
        handler: async ({ status, amount, method }) => {
            //Do nothing
    })

    //👇🏻 action to delete invoices
    useCopilotAction({
        name: "deleteInvoice",
        description: "Remove invoices to the invoice list",
            parameters: [
                {
                    name: "id",
                    type: "number",
                    description: "The id of the invoice to remove.",
                    required: true,
                },
        ],
        render: ({ status, args }) => {
            const { id } = args;
            if (id === undefined) return "";
            const getInvoice = invoiceList.find((item) => item.id === id);
            if (!getInvoice) return ""

            const deleteInvoice = () => { 
                setInvoiceList((prev) => {
                    return prev.filter((item) => item.id !== id);
                });
            }

            return (
                <div className="w-full p-2">
                    <p className="text-sm text-blue-400 mb-2">Status: {status}</p>
                    <TableComponent invoiceList={[getInvoice]} />
                    <button className="px-4 py-2 bg-blue-400 text-white shadow rounded-md" onClick={deleteInvoice}>Delete</button>
                </div>

            )
        },
        handler: async ({) => {
            // Do nothing
        }
    })

addNewInvoicedeleteInvoice操作在執行使用者的請求後呈現React 元件(生成式UI),允許使用者透過點擊按鈕將結果新增至頁面。

使用 CopilotKit 中的生成式 UI 新增和刪除發票

最後,新增建立、更新和刪除待辦事項的操作。

 //👇🏻 action to update todo status
    useCopilotAction({
        name: "toggleTodo",
        description: "Toggle the completion status of a todo item.",
        parameters: [
            {
                name: "id",
                type: "number",
                description: "The id of the todo item to toggle.",
                required: true,
            },
        ],
        render: ({ status, args }) => {
            const { id } = args;
            if (id === undefined) return "";
            const getTodo = todoList.find((item) => item.id === id);
            if (!getTodo) return "";

            const toggleTodo = () => {
                setTodoList(
                    todoList.map((todo) => {
                        if (todo.id === id) {
                            return { ...todo, completed: !todo.completed };
                        }
                        return todo;
                    })
                );
            };
            return (
                <div className="w-full p-2">
                    <p className="text-sm text-blue-400 mb-2">Status: {status}</p>
                    <CheckboxComponent todoList={[getTodo]} setTodoList={setTodoList} />
                    <button className="px-4 py-2 bg-blue-400 text-white shadow rounded-md" onClick={toggleTodo}>Toggle Todo</button>
                </div>
            )

        },
        handler: async () => {
            // Do nothing
        },
    })

    //👇🏻 action to add new todo
    useCopilotAction({
        name: "addNewTodo",
        description: "Add new todo to the todo list",
        parameters: [
            {
                name: "text",
                type: "string",
                description: "The text of the todo item.",
                required: true,
            },
        ],
        render: ({ status, args }) => {
            const { text } = args;
            if (text === undefined) return "";

            const addTodo = () => {
                setTodoList((prev) => {
                    return [...prev, { id: prev.length + 1, text, completed: false }];
                });
            };
            return (
                <div className="w-full p-2">
                    <p className="text-sm text-blue-400 mb-2">Status: {status}</p>
                    <CheckboxComponent todoList={[...todoList, { id: todoList.length + 1, text, completed: false }]} setTodoList={setTodoList} />
                    <button className="px-4 py-2 bg-blue-400 text-white shadow rounded-md" onClick={addTodo}>Add to Page</button>
                </div>
            )

        },
        handler: async () => {
            // Do nothing
        },
    });

    //👇🏻 action to delete todo
    useCopilotAction({
        name: "deleteTodo",
        description: "Remove todo from the todo list",
        parameters: [
            {
                name: "id",
                type: "number",
                description: "The id of the todo item to remove.",
                required: true,
            },
        ],
        render: ({ status, args }) => { 
            const { id } = args;
            if (id === undefined) return "";
            const getTodo = todoList.find((item) => item.id === id);
            if (!getTodo) return "";

            const deleteTodo = () => {
                setTodoList((prev) => {
                    return prev.filter((item) => item.id !== id);
                });
            };
            return (
                <div className="w-full p-2">
                    <p className="text-sm text-blue-400 mb-2">Status: {status}</p>
                    <CheckboxComponent todoList={[getTodo]} setTodoList={setTodoList} />
                    <button className="px-4 py-2 bg-red-500 text-white shadow rounded-md" onClick={deleteTodo}>Delete</button>
                </div>
            )
        },
        handler: async ({ id }) => {
            // Do nothing
        },
    });

toggleTodo操作切換待辦事項的狀態。 addNewTodo操作建立一個新的待辦事項, deleteTodo操作透過其 ID 刪除待辦事項。

示範展示 CopilotKit 生成式 UI 的工作原理

恭喜!您已完成本教學的專案。

以下是該應用程式的簡短演示:

{% 嵌入 https://youtu.be/\_Sxel4urBRY %}


結論

CopilotKit 是一款令人難以置信的工具,可讓您在幾分鐘內將 AI Copilot 加入到您的產品中。無論您是對人工智慧聊天機器人和助理感興趣,還是對複雜任務的自動化感興趣,CopilotKit 都能讓您輕鬆實現。

如果您需要建立 AI 產品或將 AI 工具整合到您的軟體應用程式中,您應該考慮 CopilotKit。

您可以在 GitHub 上找到本教學的源程式碼:

https://github.com/dha-stix/interactive-sales-dashboard-with-copilokit

感謝您的閱讀!


原文出處:https://dev.to/copilotkit/how-i-upped-my-frontend-game-with-generative-ui-4fhc


共有 0 則留言