待辦事項清單是每個開發人員的經典專案。在當今世界,學習如何使用人工智慧進行建構並在你的投資組合中加入一些人工智慧專案是很棒的。
今天,我將逐步介紹如何使用嵌入式 AI 副駕駛來建立待辦事項列表,以實現一些 AI 魔法🪄。
我們將介紹如何:
使用 Next.js、TypeScript 和 Tailwind CSS 建立待辦事項清單產生器 Web 應用。
使用 CopilotKit 將 AI 功能整合到待辦事項清單產生器中。
使用 AI 聊天機器人新增清單、將清單分配給某人、將清單標記為已完成以及刪除清單。
CopilotKit是一個開源的AI副駕駛框架。我們可以輕鬆地將強大的人工智慧整合到您的 React 應用程式中。
建造:
ChatBot:上下文感知的應用內聊天機器人,可以在應用程式內執行操作 💬
CopilotTextArea:人工智慧驅動的文字字段,具有上下文感知自動完成和插入功能📝
聯合代理:應用程式內人工智慧代理,可以與您的應用程式和使用者互動🤖
{% cta https://go.copilotkit.ai/bonnie %} 明星 CopilotKit ⭐️ {% endcta %}
要完全理解本教程,您需要對 React 或 Next.js 有基本的了解。
以下是建立人工智慧驅動的待辦事項清單產生器所需的工具:
Nanoid - 一個小型、安全、URL 友善、唯一的 JavaScript 字串 ID 產生器。
OpenAI API - 提供 API 金鑰,讓您能夠使用 ChatGPT 模型執行各種任務。
CopilotKit - 一個開源副駕駛框架,用於建立自訂 AI 聊天機器人、應用程式內 AI 代理程式和文字區域。
首先,透過在終端機中執行以下程式碼片段來建立 Next.js 應用程式:
npx create-next-app@latest todolistgenerator
選擇您首選的配置設定。在本教學中,我們將使用 TypeScript 和 Next.js App Router。
接下來,安裝 Nanoid 套件及其相依性。
npm i nanoid
最後,安裝 CopilotKit 軟體套件。這些套件使我們能夠從 React 狀態檢索資料並將 AI copilot 新增至應用程式。
npm install @copilotkit/react-ui @copilotkit/react-textarea @copilotkit/react-core @copilotkit/backend @copilotkit/shared
恭喜!您現在已準備好建立由人工智慧驅動的待辦事項清單產生器。
在本節中,我將引導您完成使用靜態內容建立待辦事項清單產生器前端的過程,以定義生成器的使用者介面。
首先,請在程式碼編輯器中前往/[root]/src/app
並建立一個名為types
資料夾。在 types 資料夾中,建立一個名為todo.ts
的文件,並新增以下程式碼來定義名為Todo
的 TypeScript 介面。
Todo
介面定義了一個物件結構,其中每個待辦事項都必須具有id
、 text
和isCompleted
狀態,同時也可以選擇具有assignedTo
屬性。
export interface Todo {
id: string;
text: string;
isCompleted: boolean;
assignedTo?: string;
}
然後轉到程式碼編輯器中的/[root]/src/app
並建立一個名為components
的資料夾。在 Components 資料夾中,建立三個名為Header.tsx
、 TodoList.tsx
和TodoItem.tsx
的檔案。
在Header.tsx
檔案中,新增以下程式碼,定義一個名為Header
的功能元件,該元件將呈現生成器的導覽列。
import Link from "next/link";
export default function Header() {
return (
<>
<header className="flex flex-wrap sm:justify-start sm:flex-nowrap z-50 w-full bg-gray-800 border-b border-gray-200 text-sm py-3 sm:py-0 ">
<nav
className="relative max-w-7xl w-full mx-auto px-4 sm:flex sm:items-center sm:justify-between sm:px-6 lg:px-8"
aria-label="Global">
<div className="flex items-center justify-between">
<Link
className="w-full flex-none text-xl text-white font-semibold p-6"
href="/"
aria-label="Brand">
To-Do List Generator
</Link>
</div>
</nav>
</header>
</>
);
}
在TodoItem.tsx
檔案中,新增以下程式碼來定義名為TodoItem
的 React 功能元件。它使用 TypeScript 來確保類型安全性並定義元件接受的 props。
import { Todo } from "../types/todo"; // Importing the Todo type from a types file
// Defining the interface for the props that the TodoItem component will receive
interface TodoItemProps {
todo: Todo; // A single todo item
toggleComplete: (id: string) => void; // Function to toggle the completion status of a todo
deleteTodo: (id: string) => void; // Function to delete a todo
assignPerson: (id: string, person: string | null) => void; // Function to assign a person to a todo
hasBorder?: boolean; // Optional prop to determine if the item should have a border
}
// Defining the TodoItem component as a functional component with the specified props
export const TodoItem: React.FC<TodoItemProps> = ({
todo,
toggleComplete,
deleteTodo,
assignPerson,
hasBorder,
}) => {
return (
<div
className={
"flex items-center justify-between px-4 py-2 group" +
(hasBorder ? " border-b" : "") // Conditionally adding a border class if hasBorder is true
}>
<div className="flex items-center">
<input
className="h-5 w-5 text-blue-500"
type="checkbox"
checked={todo.isCompleted} // Checkbox is checked if the todo is completed
onChange={() => toggleComplete(todo.id)} // Toggle completion status on change
/>
<span
className={`ml-2 text-sm text-white ${
todo.isCompleted ? "text-gray-500 line-through" : "text-gray-900" // Apply different styles if the todo is completed
}`}>
{todo.assignedTo && (
<span className="border rounded-md text-xs py-[2px] px-1 mr-2 border-purple-700 uppercase bg-purple-400 text-black font-medium">
{todo.assignedTo} {/* Display the assigned person's name if available */}
</span>
)}
{todo.text} {/* Display the todo text */}
</span>
</div>
<div>
<button
onClick={() => deleteTodo(todo.id)} // Delete the todo on button click
className="text-red-500 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-5 h-5">
<path
strokeLinecap="round"
strokeLinejoin="round"
d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"
/>
</svg>
</button>
<button
onClick={() => {
const name = prompt("Assign person to this task:");
assignPerson(todo.id, name);
}}
className="ml-2 text-blue-500 opacity-0 group-hover:opacity-100 transition-opacity duration-200">
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
strokeWidth={1.5}
stroke="currentColor"
className="w-5 h-5">
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M18 7.5v3m0 0v3m0-3h3m-3 0h-3m-2.25-4.125a3.375 3.375 0 1 1-6.75 0 3.375 3.375 0 0 1 6.75 0ZM3 19.235v-.11a6.375 6.375 0 0 1 12.75 0v.109A12.318 12.318 0 0 1 9.374 21c-2.331 0-4.512-.645-6.374-1.766Z"
/>
</svg>
</button>
</div>
</div>
);
};
在TodoList.tsx
檔案中,加入以下程式碼來定義名為TodoList
的 React 功能元件。此元件用於管理和顯示待辦事項清單。
"use client";
import { TodoItem } from "./TodoItem"; // Importing the TodoItem component
import { nanoid } from "nanoid"; // Importing the nanoid library for generating unique IDs
import { useState } from "react"; // Importing the useState hook from React
import { Todo } from "../types/todo"; // Importing the Todo type
// Defining the TodoList component as a functional component
export const TodoList: React.FC = () => {
// State to hold the list of todos
const [todos, setTodos] = useState<Todo[]>([]);
// State to hold the current input value
const [input, setInput] = useState("");
// Function to add a new todo
const addTodo = () => {
if (input.trim() !== "") {
// Check if the input is not empty
const newTodo: Todo = {
id: nanoid(), // Generate a unique ID for the new todo
text: input.trim(), // Trim the input text
isCompleted: false, // Set the initial completion status to false
};
setTodos([...todos, newTodo]); // Add the new todo to the list
setInput(""); // Clear the input field
}
};
// Function to handle key press events
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === "Enter") {
// Check if the Enter key was pressed
addTodo(); // Add the todo
}
};
// Function to toggle the completion status of a todo
const toggleComplete = (id: string) => {
setTodos(
todos.map((todo) =>
todo.id === id ? { ...todo, isCompleted: !todo.isCompleted } : todo
)
);
};
// Function to delete a todo
const deleteTodo = (id: string) => {
setTodos(todos.filter((todo) => todo.id !== id));
};
// Function to assign a person to a todo
const assignPerson = (id: string, person: string | null) => {
setTodos(
todos.map((todo) =>
todo.id === id
? { ...todo, assignedTo: person ? person : undefined }
: todo
)
);
};
return (
<div>
<div className="flex mb-4">
<input
className="border rounded-md p-2 flex-1 mr-2"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={handleKeyPress} // Add this to handle the Enter key press
/>
<button
className="bg-blue-500 rounded-md p-2 text-white"
onClick={addTodo}>
Add Todo
</button>
</div>
{todos.length > 0 && ( // Check if there are any todos
<div className="border rounded-lg">
{todos.map((todo, index) => (
<TodoItem
key={todo.id} // Unique key for each todo item
todo={todo} // Pass the todo object as a prop
toggleComplete={toggleComplete} // Pass the toggleComplete function as a prop
deleteTodo={deleteTodo} // Pass the deleteTodo function as a prop
assignPerson={assignPerson} // Pass the assignPerson function as a prop
hasBorder={index !== todos.length - 1} // Conditionally add a border to all but the last item
/>
))}
</div>
)}
</div>
);
};
接下來,前往/[root]/src/page.tsx
文件,新增以下程式碼,匯入TodoList
和Header
元件並定義名為Home
的功能元件。
import Header from "./components/Header";
import { TodoList } from "./components/TodoList";
export default function Home() {
return (
<>
<Header />
<div className="border rounded-md max-w-2xl mx-auto p-4 mt-4">
<h1 className="text-2xl text-white font-bold mb-4">
Create a to-do list
</h1>
<TodoList />
</div>
</>
);
}
接下來,刪除globals.css
檔案中的 CSS 程式碼並新增以下 CSS 程式碼。
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
height: 100vh;
background-color: rgb(16, 23, 42);
}
最後,在命令列上執行命令npm run dev
,然後導航到 http://localhost:3000/。
現在您應該在瀏覽器上查看待辦事項清單產生器前端,如下所示。
在本節中,您將學習如何將 AI 副駕駛新增至待辦事項清單產生器,以使用 CopilotKit 產生清單。
CopilotKit 提供前端和後端套件。它們使您能夠插入 React 狀態並使用 AI 代理在後端處理應用程式資料。
首先,我們將 CopilotKit React 元件新增至待辦事項清單產生器前端。
在這裡,我將引導您完成將待辦事項清單產生器與 CopilotKit 前端整合以促進清單產生的過程。
首先,使用下面的程式碼片段匯入/[root]/src/app/components/TodoList.tsx
檔案頂部的useCopilotReadable
和useCopilotAction
自訂掛鉤。
import { useCopilotAction, useCopilotReadable } from "@copilotkit/react-core";
在TodoList
函數內的狀態變數下方,新增以下程式碼,該程式碼使用useCopilotReadable
掛鉤來新增將作為應用程式內聊天機器人的上下文產生的待辦事項清單。該鉤子使副駕駛可以讀取待辦事項清單。
useCopilotReadable({
description: "The user's todo list.",
value: todos,
});
在上面的程式碼下方,新增以下程式碼,該程式碼使用useCopilotAction
掛鉤來設定名為updateTodoList
的操作,該操作將啟用待辦事項清單的產生。
此操作採用一個名為 items 的參數,該參數可以產生待辦事項列表,並包含一個根據給定提示產生待辦事項列表的處理程序函數。
在處理函數內部, todos
狀態會使用新產生的 todo 清單進行更新,如下所示。
// Define the "updateTodoList" action using the useCopilotAction function
useCopilotAction({
// Name of the action
name: "updateTodoList",
// Description of what the action does
description: "Update the users todo list",
// Define the parameters that the action accepts
parameters: [
{
// The name of the parameter
name: "items",
// The type of the parameter, an array of objects
type: "object[]",
// Description of the parameter
description: "The new and updated todo list items.",
// Define the attributes of each object in the items array
attributes: [
{
// The id of the todo item
name: "id",
type: "string",
description:
"The id of the todo item. When creating a new todo item, just make up a new id.",
},
{
// The text of the todo item
name: "text",
type: "string",
description: "The text of the todo item.",
},
{
// The completion status of the todo item
name: "isCompleted",
type: "boolean",
description: "The completion status of the todo item.",
},
{
// The person assigned to the todo item
name: "assignedTo",
type: "string",
description:
"The person assigned to the todo item. If you don't know, assign it to 'YOU'.",
// This attribute is required
required: true,
},
],
},
],
// Define the handler function that executes when the action is invoked
handler: ({ items }) => {
// Log the items to the console for debugging purposes
console.log(items);
// Create a copy of the existing todos array
const newTodos = [...todos];
// Iterate over each item in the items array
for (const item of items) {
// Find the index of the existing todo item with the same id
const existingItemIndex = newTodos.findIndex(
(todo) => todo.id === item.id
);
// If an existing item is found, update it
if (existingItemIndex !== -1) {
newTodos[existingItemIndex] = item;
}
// If no existing item is found, add the new item to the newTodos array
else {
newTodos.push(item);
}
}
// Update the state with the new todos array
setTodos(newTodos);
},
// Provide feedback or a message while the action is processing
render: "Updating the todo list...",
});
在上面的程式碼下方,新增以下程式碼,程式碼使用useCopilotAction
掛鉤來設定名為deleteTodo
的操作,該操作使您能夠刪除待辦事項。
該操作採用名為id 的參數,該參數可讓您透過id 刪除待辦事項,並包含一個處理函數,該函數透過過濾掉具有給定id 的已刪除待辦事項來更新待辦事項狀態。
// Define the "deleteTodo" action using the useCopilotAction function
useCopilotAction({
// Name of the action
name: "deleteTodo",
// Description of what the action does
description: "Delete a todo item",
// Define the parameters that the action accepts
parameters: [
{
// The name of the parameter
name: "id",
// The type of the parameter, a string
type: "string",
// Description of the parameter
description: "The id of the todo item to delete.",
},
],
// Define the handler function that executes when the action is invoked
handler: ({ id }) => {
// Update the state by filtering out the todo item with the given id
setTodos(todos.filter((todo) => todo.id !== id));
},
// Provide feedback or a message while the action is processing
render: "Deleting a todo item...",
});
之後,請前往/[root]/src/app/page.tsx
檔案並使用下面的程式碼匯入頂部的 CopilotKit 前端套件和樣式。
import { CopilotKit } from "@copilotkit/react-core";
import { CopilotPopup } from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";
然後使用CopilotKit
包裝CopilotPopup
和TodoList
元件,如下所示。 CopilotKit
元件指定 CopilotKit 後端端點 ( /api/copilotkit/
) 的 URL,而CopilotPopup
則呈現應用程式內聊天機器人,您可以提示產生待辦事項清單。
export default function Home() {
return (
<>
<Header />
<div className="border rounded-md max-w-2xl mx-auto p-4 mt-4">
<h1 className="text-2xl text-white font-bold mb-4">
Create a to-do list
</h1>
<CopilotKit runtimeUrl="/api/copilotkit">
<TodoList />
<CopilotPopup
instructions={
"Help the user manage a todo list. If the user provides a high level goal, " +
"break it down into a few specific tasks and add them to the list"
}
defaultOpen={true}
labels={{
title: "Todo List Copilot",
initial: "Hi you! 👋 I can help you manage your todo list.",
}}
clickOutsideToClose={false}
/>
</CopilotKit>
</div>
</>
);
}
之後,執行開發伺服器並導航至http://localhost:3000 。您應該會看到應用程式內聊天機器人已整合到待辦事項清單產生器中。
在這裡,我將引導您完成將待辦事項清單產生器與 CopilotKit 後端整合的過程,該後端處理來自前端的請求,並提供函數呼叫和各種 LLM 後端(例如 GPT)。
首先,在根目錄中建立一個名為.env.local
的檔案。然後將下面的環境變數加入到儲存ChatGPT
API 金鑰的檔案中。
OPENAI_API_KEY="Your ChatGPT API key”
若要取得 ChatGPT API 金鑰,請導覽至 https://platform.openai.com/api-keys。
之後,轉到/[root]/src/app
並建立一個名為api
的資料夾。在api
資料夾中,建立一個名為copilotkit
的資料夾。
在copilotkit
資料夾中,建立一個名為route.ts
的文件,其中包含設定後端功能以處理POST 請求的程式碼。
// Import the necessary modules from the "@copilotkit/backend" package
import { CopilotRuntime, OpenAIAdapter } from "@copilotkit/backend";
// Define an asynchronous function to handle POST requests
export async function POST(req: Request): Promise<Response> {
// Create a new instance of CopilotRuntime
const copilotKit = new CopilotRuntime({});
// Use the copilotKit to generate a response using the OpenAIAdapter
// Pass the incoming request (req) and a new instance of OpenAIAdapter to the response method
return copilotKit.response(req, new OpenAIAdapter());
}
現在轉到您之前整合的應用程式內聊天機器人,並給它一個提示,例如「我想去健身房做全身運動。加入到我應該遵循的鍛煉程序列表”
生成完成後,您應該會看到應遵循的全身運動程序列表,如下所示。
您可以透過向聊天機器人發出「將待辦事項清單指派給 Doe」之類的提示來將待辦事項清單指派給某人。
您可以透過向聊天機器人提供「將待辦事項清單標記為已完成」等提示來將待辦事項清單標記為已完成。
您可以透過向聊天機器人發出「刪除待辦事項清單」之類的提示來刪除待辦事項清單。
恭喜!您已完成本教學的專案。
CopilotKit是一款令人難以置信的工具,可讓您在幾分鐘內將 AI Copilot 加入到您的產品中。無論您是對人工智慧聊天機器人和助理感興趣,還是對複雜任務的自動化感興趣,CopilotKit 都能讓您輕鬆實現。
如果您需要建立 AI 產品或將 AI 工具整合到您的軟體應用程式中,您應該考慮 CopilotKit。
您可以在 GitHub 上找到本教學的源程式碼:https://github.com/TheGreatBonnie/AIpoweredToDoListGenerator
原文出處:https://dev.to/copilotkit/how-to-build-an-ai-powered-to-do-list-nextjs-gpt4-copilotkit-20i4