手记

在Next.js中打造最强AI日程助手实战教程

重点 或 简单来说

读完这篇文章,你将学会如何

  • 在你的 Next.js 应用中集成一个 AI 合作伙伴,通过使用 Cal.com 构建一个日程安排的应用。

  • 开发并管理一个自定义调度器,以提升应用内的用户体验,从而增强用户在整个应用中的体验。

更重要的是,你还将有一个酷炫的项目作品可以展示在你的作品集里。

此处省略内容

你知道什么是AI副驾助手吗?

一个AI助手是在应用内的人工智能助手,它帮助用户解决问题并执行操作。它将大语言模型的智能直接融入您的应用程序。

以下是一些AI副驾可能的应用场景:

  • ChatBot:一种应用程序内的上下文消息服务,可以帮助用户解决问题并在应用程序中执行特定任务。
  • AI 自动补全:智能输入控件,可以在用户输入消息时提供实时建议。
  • CoAgents:能够与您的应用程序和用户直接互动和协助的智能助手,能够独立完成复杂的任务。

CopilotKit 是构建内置 AI 助手的最领先、最强大且最易用的开源框架。只需短短几分钟,你就能在应用中运行一个完全定制的 AI 助手。

查看一下 CopilotKit ⭐️

此处省略部分内容

前提条件

要跟上这个教程,你需要以下这些东西。

  • 熟悉Next.jsTypeScript
  • 您的计算机上已安装NPMNode.js
  • 有一个CopilotKit账户,这是一个开源的副驾框架,用于构建自定义AI聊天机器人、应用程序内AI代理以及文本组件。
  • 有一个Cal.com账户,如果您还没有,请按照此指南创建一个账户。

这里我们将在这教程中展示的是一个示范:

新建一个 Next.js 项目

Next.js 是创建可扩展和高性能 web 应用程序的最常用的框架之一。它基于 React 核心功能,并提供了服务器端渲染、静态站点生成和更简单的路由,帮助创建快速、生产就绪的网站,拥有良好的 SEO。

为了让我们能够专注于学习如何将Cal.com和Copilot集成到您的房间预订Next.js应用中,我已经为此应用创建了组件和UI界面。运行如下命令来克隆并运行该应用:

在终端输入以下命令来克隆仓库并安装依赖:

git clone https://github.com/icode247/copilot-booking-app 
&& cd copilot-booking-app && npm install && npm run dev

全屏显示;退出全屏

集成Cal.com API进行预订

现在定义这些路由如下。在这些路由中,我们将向 Cal.com API 发送 API 调用来创建新的预约记录或取消预约记录。在你的 API 目录中,创建一个新的 bookings/route.ts 文件,并在其中添加以下代码。

    import { NextRequest, NextResponse } from 'next/server';
    import axios from 'axios';

    export async function POST(request: NextRequest) {
      const { room, start, end, time, email } = await request.json();

      try {
        const [startDate] = start.split("T");
        const startDateTime = new Date(`${startDate}T${time}:00`);
        const formattedStart = startDateTime.toISOString();

        const endDateTime = new Date(startDateTime);
        endDateTime.setHours(endDateTime.getHours() + 1);
        const formattedEnd = endDateTime.toISOString();

        // 第一步:创建事件类型
        const eventTypePayload = {
          length: 60,
          slug: `booking-${Date.now()}-${room.toLowerCase().replace(/\s+/g, "-")}`,
          title: `预订 ${room}`,
          description: `从 ${formattedStart} 到 ${formattedEnd} 的 ${room} 预订`,
          locations: [{ type: "inPerson", address: room }],
          disableGuests: false,
          slotInterval: 0,
          minimumBookingNotice: 0,
          beforeEventBuffer: 0,
          afterEventBuffer: 0,
        };

        const eventTypeResponse = await axios.post(
          `${CALCOM_API_BASE_URL}/event-types`,
          eventTypePayload,
          {
            headers: {
              "Content-Type": "application/json",
              Authorization: `Bearer ${process.env.NEXT_PUBLIC_CALCOM_API_KEY}`,
            },
          }
        );

        const eventTypeId = eventTypeResponse.data.data.id;

        // 第二步:创建预订
        const bookingPayload = {
          end: formattedEnd,
          start: formattedStart,
          eventTypeId,
          eventTypeSlug: eventTypePayload.slug,
          timeZone: "Africa/Lagos",
          user: [email],
          language: "en",
          bookingUid: `booking-${Date.now()}`,
          metadata: {},
          responses: {
            name: email.split("@")[0],
            email,
            guests: [],
            notes: `从 ${formattedStart} 到 ${formattedEnd} 的 ${room} 预订`,
          },
        };

        const bookingResponse = await axios.post(
          `${process.env.CALCOM_API_BASE_URL}/bookings`,
          bookingPayload,
          {
            headers: {
              "Content-Type": "application/json",
              Authorization: `Bearer ${process.env.NEXT_PUBLIC_CALCOM_API_KEY}`,
            },
          }
        );

        return NextResponse.json({ booking: bookingResponse.data }, { status: 201 });
      } catch (error) {
        console.error("错误响应状态:", error.response?.status);
        return NextResponse.json(
          {
            error: "预订失败",
            details: error.response?.data || error.message,
          },
          { status: 500 }
        );
      }
    }

全屏开启 全屏关闭

上述代码将在Cal.com创建一个包含预订详情(如房间和时间信息)的事件类型。接着,利用新创建的事件类型的ID,在Cal.com上创建具体的预订。此外,该代码处理日期格式,构建两个API调用所需的负载,并使用axios发送请求给Cal.com API。

创建一个新的cancel/route.ts文件,并在其中加入以下代码:

    从“next/server”导入{ NextRequest, NextResponse };
    从“axios”导入axios;

    export async function POST(
      request: NextRequest,
      { params }: { params: { id: string } }
    ) {
      try {
        const body = await request.json();
        const bookingId = params.id;

        const 取消预订响应 = await axios.post(
          `${process.env.CALCOM_API_BASE_URL}/bookings/${bookingId}/cancel`,
          body,
          {
            headers: {
              "Content-Type": "application/json",
              Authorization: `Bearer ${process.env.NEXT_PUBLIC_CALCOM_API_KEY}`,
            },
          }
        );

        return NextResponse.json(
          { 预订: 取消预订响应.data },
          { 状态: 201 }
        );
      } catch (error) {
        console.error(`取消预订失败:${error}`);
        return NextResponse.json(
          { 错误: "取消预订失败" },
          { 状态: 500 }
        );
      }
    }

全屏 开启 全屏 退出

上述代码实现了一个使用Cal.com API来取消预约的API路由处理器。

现在更新你的 app/page.tsx 文件来使用我们刚做的 RoomBookingProvider

// app/page.tsx
'use client';

import Layout from "@/components/Layout";
import RoomBookingCard from "@/components/RoomBookingCard";
import { RoomBookingProvider } from "@/lib/hooks/use-room-booking";

export default function Home() {
  return (
    <RoomBookingProvider>
      <Layout>
        <RoomBookingCard />
      </Layout>
    </RoomBookingProvider>
  );
}

// 主页面,导入布局组件和房间预订卡组件,并提供房间预订的上下文

全屏 退出全屏

接着,更新这个 RoomBookingCard.tsx 文件,使用 useRoomBooking 钩子让用户能够预订房间。

    // components/会议室预订组件.tsx
    // 客户端使用

    import { FC, useEffect, useState } from "react";
    import 会议室列表 from "./会议室列表";
    import 通知 from "./通知";
    import 预订表单 from "./预订表单";
    import { useRoomBooking } from "@/lib/hooks/use-room-booking";

    const RoomBookingCard: FC = () => {
      const [selected, setSelectedRoom] = useState<string | null>(null);
      const [notification, setNotification] = useState<string | null>(null);
      const [rooms, setRooms] = useState([]);
      const { addBooking } = useRoomBooking();

      useEffect(() => {
        async function fetchRooms() {
          const response = await fetch("/api/rooms");
          const data = await response.json();
          setRooms(data);
        }
        fetchRooms();
      }, []);

      const handleSelect = (会议室: string) => {
        setSelectedRoom(会议室);
      };

      const handleConfirm = async (
        开始日期: string,
        时间: string,
        结束日期: string,
        邮箱: string
      ) => {
        try {
          if (selected) {
            await addBooking(selected, 开始日期, 时间, 结束日期, 邮箱);
            setNotification("预订已确认!");
            setSelectedRoom(null);
          }
        } catch (error) {
          setNotification(error.message);
        }
      };

      return (
        <div>
          {notification && (
            <通知
              message={notification}
              onClose={() => setNotification(null)}
            />
          )}
          {selected ? (
            <预订表单 room={selected} onConfirm={handleConfirm} />
          ) : (
            <会议室列表 rooms={rooms} onSelectRoom={handleSelect} />
          )}
        </div>
      );
    };

    export default RoomBookingCard;

全屏,退出全屏

你现在可以选择任何房间,填写你的信息并预订这个房间。

接下来,让我们通过添加使用CopilotKit的AI助手来使应用程序更有趣味。首先,访问OpenAI开发者平台并创建一个新的密钥(API密钥)。

集成 Copilotkit,实现 AI 互动

设置: Copilotkit

Copilotkit 提供了两种集成方式。

  • Copilot 云服务: 最简单的方式开始使用 CopilotKit 是怎样的?
  • 自建部署: 这会在您自己的基础设施上部署一个 Copilot 运行时实例。

对于本教程,我们将使用Copilot Cloud。点击这里免费获取您的Copilot Cloud API密钥。接下来,将<your-public-api-key>替换为您自己的OpenAI密钥,以获取您的Copilot公开密钥。

将您的 API密钥安全地添加到您的 .env.local 文件里:

PUBLIC_API_KEY (公共API密钥)= 请替换为您的实际密钥

全屏模式 全屏退出

更新你的 app/page.tsx 文件中的代码,在你的应用中将 <CopilotKit> 提供者包裹使用,并确保这样使用。

    // app/page.tsx
    "use client";

    import Layout from "@/components/Layout";
    import RoomBookingCard from "@/components/RoomBookingCard";
    import { RoomBookingProvider } from "@/lib/hooks/use-room-booking";
    import { CopilotKit } from "@copilotkit/react-core";
    import { CopilotPopup } from "@copilotkit/react-ui";
    import "@copilotkit/react-ui/styles.css";

    export default function Home() {
      return (
        <CopilotKit publicApiKey={process.env.PUBLIC_API_KEY}>
          <RoomBookingProvider>
            <Layout>
              <RoomBookingCard />
            </Layout>
          </RoomBookingProvider>
          <CopilotPopup />
        </CopilotKit>
      );
    }

点击进入全屏模式 点击退出全屏模式

在上面的代码中,我们从 @copilotkit/react-ui 导入了 <CopilotPopup /> 组件,并用 <CopilotKit> 提供者包裹了页面。我们还从同一包中导入了可选的内置样式,来增强 UI。

现在你会看到右下角弹出的聊天窗口。

看看这个弹窗吧!

为了让Copilot给出正确的答案并执行任务,我们需要使用useCopilotReadable这个钩子让Copilot知道我们的应用状态。在你的lib/hooks/use-room-booking.tsx文件中更新代码,以提供预订和房间的状态给Copilot:

    // ...

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

    export function RoomBookingProvider({ children }: { children: ReactNode }) {
        // ... 
        const [rooms, setRooms] = useState([]);

        // ... 

        useCopilotReadable({
           description: "预订状态列表",
           value: JSON.stringify(bookings),
        });

        useCopilotReadable({
           description: "房间状态列表",
           value: JSON.stringify(rooms),
        });
        //...
    }

全屏,退出

你现在可以试试Copilot,问一下你有多少的预订。

处理预订和取消事宜

让我们让Copilot执行更多任务,比如创建预订、取消预订以及了解哪些房间可用。我们将使用CopilotuseCopilotAction 钩子来实现这一点。这个钩子可以让Copilot执行某些操作。

更新您的 lib/hooks/use-room-booking.tsx 文件,并添加以下行为:

    // ...

    export function RoomBookingProvider({ children }: { children: ReactNode }) {
    // ...

      useCopilotAction({
        name: "addBooking",
        description: "添加预订",
        parameters: [
          {
            name: "room",
            type: "string",
            description: "要预订的房间",
            required: true,
          },
          {
            name: "date",
            type: "string",
            description: "预订的日期",
            required: true,
          },
          {
            name: "time",
            type: "string",
            description: "预订的时间",
            required: true,
          },
          {
            name: "end",
            type: "string",
            description: "预订的结束时间",
            required: true,
          },
          {
            name: "email",
            type: "string",
            description: "预订该房间的用户电子邮件地址",
            required: true,
          },
        ],
        handler: async ({ room, date, time, end, email }) => {
          await addBooking(room, date, time, end, email);
        },
      });

      useCopilotAction({
        name: "cancelBooking",
        description: "取消预订",
        parameters: [
          { name: "room", type: "string", description: "取消该预订的房间", required: true },
          { name: "date", type: "string", description: "取消该预订的日期", required: true },
          { name: "reason", type: "string", description: "取消预订的理由", required: true },
        ],
        handler: async ({ room, date, reason }) => {
          await cancelBooking(room, date, reason);
        },
      });

      useCopilotAction({
        name: "fetchAvailableRooms",
        description: "获取指定日期的可用房间",
        parameters: [
          {
            name: "date",
            type: "string",
            description: "检查房间是否可用的日期",
            required: true,
          },
        ],
        handler: async ({ date }) => {
          const availableRooms = await fetchAvailableRooms(date);
          setRooms(availableRooms);
        },
      });

      useCopilotAction({
        name: "setBookingStatus",
        description: "设置预订的状态",
        parameters: [
          {
            name: "id",
            type: "number",
            description: "预订ID",
            required: true,
          },
          {
            name: "status",
            type: "string",
            description: "预订的状态",
            enum: Object.values(BookingStatus),
            required: true,
          },
        ],
        handler: ({ id, status }) => {
          setBookingStatus(id, status);
        },
      });
      //...
     }

进入全屏模式;退出全屏

在上面的代码片段中,我们使用了 useCopilotAction 钩子来创建几个动作,包括创建预订 (addBooking)、取消预订 (cancelBooking)、获取可用房间 (fetchAvailableRooms) 和设置预订状态 (setBookingStatus)。每个动作都需要一个包含以下属性的对象。

name 表示行动的名称。

description是指定义这个行动。这非常重要,因为它能让我们的智能助手选择正确的行动。

parameters 是该操作的参数列表,以数组形式存在。它遵循 JSON Schema 格式。

handler只是一个在执行操作时会被调用的函数。

现在你可以用副驾来做更复杂的事情,比如查看可用房间、预订和取消预定。随时和副驾聊天,也可以做其他事情。


用CopilotKit做高级操作

太棒了,你现在可以将这款由人工智能驱动的日程安排工具添加到你的工具中了。

……此处省略若干文字……

总结一下

CopilotKit 是一个创新且便捷的工具,用于将 AI 能力添加到您的产品中。无论是创建语音交互系统还是为复杂流程实现自动化,其适应性将满足任何想要在其工作中加入 AI 的软件开发者的需要。

如果你正在开发特别强调AI的产品,或者想要为你的应用添加AI功能,那么你应该试试看CopilotKit。这样可以节省时间并提高专注度,界面简单易用,可以迅速配置。

你对诸如CopilotKit之类的工具的好奇,帮助你跟上了软件界快速变化的格局。

加入 CopilotKit 的精彩 社区 吧!一起开发吧!

不要忘了来看看我们的GitHub,并通过给它一个⭐️来支持我们。

0人推荐
随时随地看视频
慕课网APP