如何让 AI 融入你的用户(Next.js、OpenAI、CopilotKit)
TL;DR
在本文中,您将学习如何构建一个由人工智能驱动的广告活动管理器应用程序,该应用程序允许您创建和分析广告活动,从而使您能够为您的业务做出正确的决策。
我们将介绍如何:
- 使用 Next.js 构建 Web 应用程序,
- 使用 CopilotKit 将 AI 助手集成到软件应用程序中,以及
- 创建针对特定行动的 AI 副驾驶员来处理应用程序内的各种任务。
- 建立一个活动管理器

CopilotKit:构建应用内 AI 副驾驶的框架
CopilotKit 是一个 开源的 AI 副驾驶平台。我们可以轻松地将强大的 AI 集成到你的 React 应用中。
建造:
- ChatBot:具有上下文感知能力的应用内聊天机器人,可以在应用内采取行动💬
- CopilotTextArea:具有上下文感知自动完成和插入功能的 AI 驱动文本字段📝
- 合作代理:可以与您的应用和用户交互的应用内 AI 代理🤖
先决条件
要完全理解本教程,您需要对 React 或 Next.js 有基本的了解。
我们还将利用以下内容:
- Radix UI—— 用于为应用程序创建可访问的 UI 组件。
- OpenAI API 密钥 - 使我们能够使用 GPT 模型执行各种任务。
- CopilotKit - 一个开源副驾驶框架,用于构建自定义 AI 聊天机器人、应用内 AI 代理和文本区域。
项目设置和包安装
首先,通过在终端中运行以下代码片段来创建 Next.js 应用程序:
npx create-next-app campaign-manager
选择您喜欢的配置设置。在本教程中,我们将使用 TypeScript 和 Next.js App Router。
接下来,将 Heroicons、 Radix UI及其原始组件安装到项目中。
npm install @heroicons/react @radix-ui/react-avatar @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-icons @radix-ui/react-label @radix-ui/react-popover @radix-ui/react-select @radix-ui/react-slot @radix-ui/react-tabs
另外,安装Recharts 库(用于创建交互式图表的 React 库)以及以下实用程序包:
npm install recharts class-variance-authority clsx cmdk date-fns lodash react-day-picker tailwind-merge tailwindcss-animate
最后,安装 CopilotKit 软件包。这些软件包使 AI 副驾驶能够从 React 状态中检索数据并在应用程序内做出决策。
npm install @copilotkit/react-ui @copilotkit/react-textarea @copilotkit/react-core @copilotkit/backend
恭喜!您现在可以构建应用程序了。
使用 Next.js 构建 Campaign Manager 应用
在本节中,我将引导您构建活动管理器应用程序的用户界面。
首先,让我们做一些初始设置。
在文件夹中创建一个components
和文件夹。lib
src
cd src
mkdir components lib
在该lib
文件夹中,我们将声明应用程序的静态类型和默认活动。因此,请在该文件夹中创建data.ts
和types.ts
文件lib
。
cd lib
touch data.ts type.ts
将以下代码片段复制到type.ts
文件中。该代码片段声明了广告系列属性及其数据类型。
export interface Campaign {
id: string;
objective?:
| "brand-awareness"
| "lead-generation"
| "sales-conversion"
| "website-traffic"
| "engagement";
title: string;
keywords: string;
url: string;
headline: string;
description: string;
budget: number;
bidStrategy?: "manual-cpc" | "cpa" | "cpm";
bidAmount?: number;
segment?: string;
}
为应用程序创建默认活动列表并将其复制到data.ts
文件中。
import { Campaign } from "./types";
export let DEFAULT_CAMPAIGNS: Campaign[] = [
{
id: "1",
title: "CopilotKit",
url: "https://www.copilotkit.ai",
headline: "Copilot Kit - The Open-Source Copilot Framework",
description:
"Build, deploy, and operate fully custom AI Copilots. In-app AI chatbots, AI agents, AI Textareas and more.",
budget: 10000,
keywords: "AI, chatbot, open-source, copilot, framework",
},
{
id: "2",
title: "EcoHome Essentials",
url: "https://www.ecohomeessentials.com",
headline: "Sustainable Living Made Easy",
description:
"Discover our eco-friendly products that make sustainable living effortless. Shop now for green alternatives!",
budget: 7500,
keywords: "eco-friendly, sustainable, green products, home essentials",
},
{
id: "3",
title: "TechGear Solutions",
url: "https://www.techgearsolutions.com",
headline: "Innovative Tech for the Modern World",
description:
"Find the latest gadgets and tech solutions. Upgrade your life with smart technology today!",
budget: 12000,
keywords: "tech, gadgets, innovative, modern, electronics",
},
{
id: "4",
title: "Global Travels",
url: "https://www.globaltravels.com",
headline: "Travel the World with Confidence",
description:
"Experience bespoke travel packages tailored to your dreams. Luxury, adventure, relaxation—your journey starts here.",
budget: 20000,
keywords: "travel, luxury, adventure, tours, global",
},
{
id: "5",
title: "FreshFit Meals",
url: "https://www.freshfitmeals.com",
headline: "Healthy Eating, Simplified",
description:
"Nutritious, delicious meals delivered to your door. Eating well has never been easier or tastier.",
budget: 5000,
keywords: "healthy, meals, nutrition, delivery, fit",
},
];
由于我们使用 Radix UI 创建可以使用 TailwindCSS 轻松定制的基本 UI 组件,因此请在文件夹utils.ts
中创建一个文件lib
并将以下代码片段复制到该文件中。
//👉🏻 The lib folder now contains 3 files - data.ts, type.ts, util.ts
//👇🏻 Copy the code below into the "lib/util.ts" file.
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export function randomId() {
return Math.random().toString(36).substring(2, 15);
}
导航到该components
文件夹并在其中创建另外三个文件夹。
cd components
mkdir app dashboard ui
该components/app
文件夹将包含应用程序内要使用的各种组件,而仪表板文件夹包含一些元素的 UI 组件。
该ui
文件夹包含使用 Radix UI 创建的多个 UI 元素。请将 项目存储库中的这些元素复制 到该文件夹中。
恭喜!该ui
文件夹应该包含必要的 UI 元素。现在,我们可以用它们来创建应用程序所需的各种组件了。
创建应用程序 UI 组件
在这里,我将引导您创建应用程序的用户界面。
首先,找到该app/page.tsx
文件并将以下代码片段粘贴到其中。该文件渲染components/app
文件夹中声明的 App 组件。
"use client";
import { App } from "@/components/app/App";
export default function DashboardPage() {
return <App />;
}
在文件夹中创建App.tsx
、CampaignForm.tsx
、MainNav.tsx
和文件。UserNav.tsx
components/app
cd components/app
touch App.tsx CampaignForm.tsx MainNav.tsx UserNav.tsx
将下面的代码片段复制到App.tsx
文件中。
"use client";
import { DEFAULT_CAMPAIGNS } from "@/lib/data";
import { Campaign } from "@/lib/types";
import { randomId } from "@/lib/utils";
import { Dashboard } from "../dashboard/Dashboard";
import { CampaignForm } from "./CampaignForm";
import { useState } from "react";
import _ from "lodash";
export function App() {
//👇🏻 default segments
const [segments, setSegments] = useState<string[]>([
"Millennials/Female/Urban",
"Parents/30s/Suburbs",
"Seniors/Female/Rural",
"Professionals/40s/Midwest",
"Gamers/Male",
]);
const [campaigns, setCampaigns] = useState<Campaign[]>(
_.cloneDeep(DEFAULT_CAMPAIGNS)
);
//👇🏻 updates campaign list
function saveCampaign(campaign: Campaign) {
//👇🏻 newly created campaign
if (campaign.id === "") {
campaign.id = randomId();
setCampaigns([campaign, ...campaigns]);
} else {
//👇🏻 existing campaign - search for the campaign and updates the campaign list
const index = campaigns.findIndex((c) => c.id === campaign.id);
if (index === -1) {
setCampaigns([...campaigns, campaign]);
} else {
campaigns[index] = campaign;
setCampaigns([...campaigns]);
}
}
}
const [currentCampaign, setCurrentCampaign] = useState<Campaign | undefined>(
undefined
);
return (
<div className='relative'>
<CampaignForm
segments={segments}
currentCampaign={currentCampaign}
setCurrentCampaign={setCurrentCampaign}
saveCampaign={(campaign) => {
if (campaign) {
saveCampaign(campaign);
}
setCurrentCampaign(undefined);
}}
/>
<Dashboard
campaigns={campaigns}
setCurrentCampaign={setCurrentCampaign}
segments={segments}
setSegments={setSegments}
/>
</div>
);
}
- 从上面的代码片段来看,
- 我为该活动创建了一个默认细分列表,并对已定义的活动列表进行了深度复制。
- 该
saveCampaign
函数接受一个活动作为参数。如果该活动没有 ID,则表示它是新创建的,因此会将其添加到活动列表中。否则,它会找到该活动并更新其属性。 Dashboard
和组件CampaignForm
接受片段和活动作为道具。
Dashboard组件在仪表板上显示各种 UI 元素,而CampaignForm 组件则使用户能够在应用程序中创建和保存新的活动。
您还可以使用GitHub 存储库中的代码片段更新仪表板和应用程序组件。
恭喜!您应该已经拥有一个可以运行的 Web 应用程序,用户可以查看和创建新的营销活动。
在接下来的部分中,您将学习如何将 CopilotKit 添加到应用程序中,以根据每个活动的目标和预算进行分析和做出决策。

使用 CopilotKit 通过 AI 分析广告活动
在这里,您将学习如何将 AI 添加到应用程序中,以帮助您分析您的活动并做出最佳决策。
在我们继续之前,请访问OpenAI 开发者平台并创建一个新的密钥。
创建一个.env.local
文件并将您新创建的密钥复制到该文件中。
OPENAI_API_KEY=<YOUR_OPENAI_SECRET_KEY>
OPENAI_MODEL=gpt-4-1106-preview
接下来,您需要为 CopilotKit 创建一个 API 端点。在 Next.js 应用文件夹中,创建一个api/copilotkit
包含route.ts
文件的文件夹。
cd app
mkdir api && cd api
mkdir copilotkit && cd copilotkit
touch route.ts
将以下代码片段复制到route.ts
文件中。CopilotKit后端接受用户请求并使用 OpenAI 模型做出决策。
import { CopilotBackend, OpenAIAdapter } from "@copilotkit/backend";
export const runtime = "edge";
export async function POST(req: Request): Promise<Response> {
const copilotKit = new CopilotBackend({});
const openaiModel = process.env["OPENAI_MODEL"];
return copilotKit.response(req, new OpenAIAdapter({ model: openaiModel }));
}
要将您的应用程序连接到此 API 端点,app/page.tsx
请按如下所示更新文件:
"use client";
import { App } from "@/components/app/App";
import { CopilotKit } from "@copilotkit/react-core";
import { CopilotSidebar } from "@copilotkit/react-ui";
export default function DashboardPage() {
return (
<CopilotKit url='/api/copilotkit/'>
<CopilotSidebar
instructions='Help the user create and manage ad campaigns.'
defaultOpen={true}
labels={{
title: "Campaign Manager Copilot",
initial:
"Hello there! I can help you manage your ad campaigns. What campaign would you like to work on?",
}}
clickOutsideToClose={false}
>
<App />
</CopilotSidebar>
</CopilotKit>
);
}
该CopilotKit
组件包装了整个应用程序,并接受一个url
包含指向 API 端点链接的 prop。该CopilotSidebar
组件向应用程序添加了一个聊天机器人侧边栏面板,使我们能够向 CopilotKit 提供各种指令。

如何让AI副驾驶执行各种操作
CopilotKit 提供了两个钩子,使我们能够处理用户的请求并插入应用程序状态:useCopilotAction和useMakeCopilotReadable。
该useCopilotAction
钩子允许您定义由 CopilotKit 执行的操作。它接受包含以下参数的对象:
- name——动作的名称。
- 描述——动作的描述。
- 参数——包含所需参数列表的数组。
- render - 默认的自定义函数或字符串。
- 处理程序——由操作触发的可执行函数。
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}!`);
},
});
该useMakeCopilotReadable
钩子向 CopilotKit 提供应用程序状态。
import { useMakeCopilotReadable } from "@copilotkit/react-core";
const appState = ...;
useMakeCopilotReadable(JSON.stringify(appState));
CopilotKit 还允许您为用户的提示提供上下文,使其能够做出充分而准确的决策。
将guidance.ts
和 添加script.ts
到lib
项目内的文件夹中,并将此指导和脚本建议复制到文件中以使 CopilotKit 做出决策。
在 App 组件内,将当前日期、脚本建议和指导传递到 CopilotKit。
import { GUIDELINE } from "@/lib/guideline";
import { SCRIPT_SUGGESTION } from "@/lib/script";
import {
useCopilotAction,
useMakeCopilotReadable,
} from "@copilotkit/react-core";
export function App() {
//-- 👉🏻 ...other component functions
//👇🏻 Ground the Copilot with domain-specific knowledge for this use-case: marketing campaigns.
useMakeCopilotReadable(GUIDELINE);
useMakeCopilotReadable(SCRIPT_SUGGESTION);
//👇🏻 Provide the Copilot with the current date.
useMakeCopilotReadable("Today's date is " + new Date().toDateString());
return (
<div className='relative'>
<CampaignForm
segments={segments}
currentCampaign={currentCampaign}
setCurrentCampaign={setCurrentCampaign}
saveCampaign={(campaign) => {
if (campaign) {
saveCampaign(campaign);
}
setCurrentCampaign(undefined);
}}
/>
<Dashboard
campaigns={campaigns}
setCurrentCampaign={setCurrentCampaign}
segments={segments}
setSegments={setSegments}
/>
</div>
);
}
在组件内创建一个 CopilotKit 操作,App
当用户提供此类指令时,该操作会创建一个新的活动或编辑现有的活动。
useCopilotAction({
name: "updateCurrentCampaign",
description:
"Edit an existing campaign or create a new one. To update only a part of a campaign, provide the id of the campaign to edit and the new values only.",
parameters: [
{
name: "id",
description:
"The id of the campaign to edit. If empty, a new campaign will be created",
type: "string",
},
{
name: "title",
description: "The title of the campaign",
type: "string",
required: false,
},
{
name: "keywords",
description: "Search keywords for the campaign",
type: "string",
required: false,
},
{
name: "url",
description:
"The URL to link the ad to. Most of the time, the user will provide this value, leave it empty unless asked by the user.",
type: "string",
required: false,
},
{
name: "headline",
description:
"The headline displayed in the ad. This should be a 5-10 words",
type: "string",
required: false,
},
{
name: "description",
description:
"The description displayed in the ad. This should be a short text",
type: "string",
required: false,
},
{
name: "budget",
description: "The budget of the campaign",
type: "number",
required: false,
},
{
name: "objective",
description: "The objective of the campaign",
type: "string",
enum: [
"brand-awareness",
"lead-generation",
"sales-conversion",
"website-traffic",
"engagement",
],
},
{
name: "bidStrategy",
description: "The bid strategy of the campaign",
type: "string",
enum: ["manual-cpc", "cpa", "cpm"],
required: false,
},
{
name: "bidAmount",
description: "The bid amount of the campaign",
type: "number",
required: false,
},
{
name: "segment",
description: "The segment of the campaign",
type: "string",
required: false,
enum: segments,
},
],
handler: (campaign) => {
const newValue = _.assign(
_.cloneDeep(currentCampaign),
_.omitBy(campaign, _.isUndefined)
) as Campaign;
setCurrentCampaign(newValue);
},
render: (props) => {
if (props.status === "complete") {
return "Campaign updated successfully";
} else {
return "Updating campaign";
}
},
});
添加另一个模拟 API 调用的操作,以允许 CopilotKit 从以前创建的活动中检索历史数据。
// Provide this component's Copilot with the ability to retrieve historical cost data for certain keywords.
// Will be called automatically when needed by the Copilot.
useCopilotAction({
name: "retrieveHistoricalData",
description: "Retrieve historical data for certain keywords",
parameters: [
{
name: "keywords",
description: "The keywords to retrieve data for",
type: "string",
},
{
name: "type",
description: "The type of data to retrieve for the keywords.",
type: "string",
enum: ["CPM", "CPA", "CPC"],
},
],
handler: async ({ type }) => {
// fake an API call that retrieves historical data for cost for certain keywords based on campaign type (CPM, CPA, CPC)
await new Promise((resolve) => setTimeout(resolve, 2000));
function getRandomValue(min: number, max: number) {
return (Math.random() * (max - min) + min).toFixed(2);
}
if (type == "CPM") {
return getRandomValue(0.5, 10);
} else if (type == "CPA") {
return getRandomValue(5, 100);
} else if (type == "CPC") {
return getRandomValue(0.2, 2);
}
},
render: (props) => {
// Custom in-chat component rendering. Different components can be rendered based on the status of the action.
let label = "Retrieving historical data ...";
if (props.args.type) {
label = `Retrieving ${props.args.type} for keywords ...`;
}
if (props.status === "complete") {
label = `Done retrieving ${props.args.type} for keywords.`;
}
const done = props.status === "complete";
return (
<div className=''>
<div className=' w-full relative max-w-xs'>
<div className='absolute inset-0 h-full w-full bg-gradient-to-r from-blue-500 to-teal-500 transform scale-[0.80] bg-red-500 rounded-full blur-3xl' />
<div className='relative shadow-xl bg-gray-900 border border-gray-800 px-4 py-8 h-full overflow-hidden rounded-2xl flex flex-col justify-end items-start'>
<h1 className='font-bold text-sm text-white mb-4 relative z-50'>
{label}
</h1>
<p className='font-normal text-base text-teal-200 mb-2 relative z-50 whitespace-pre'>
{props.args.type &&
`Historical ${props.args.type}: ${props.result || "..."}`}
</p>
</div>
</div>
</div>
);
},
});

恭喜!您已完成本教程的项目。
结论
CopilotKit 是一款功能强大的工具,可让您在几分钟内将 AI Copilot 添加到您的产品中。无论您对 AI 聊天机器人和助手感兴趣,还是对复杂任务的自动化感兴趣,CopilotKit 都能让您轻松实现。
如果您需要构建 AI 产品或将 AI 工具集成到您的软件应用程序中,您应该考虑 CopilotKit。
您可以在 GitHub 上找到本教程的源代码:
https://github.com/CopilotKit/campaign-manager-demo
感谢您的阅读!
文章来源:https://dev.to/copilotkit/build-an-ai-powered-campaign-manager-nextjs-openai-copilotkit-59ii