Imagine you're planning the ultimate vacation—a two-week tour across Europe, filled with museum visits, gourmet meals, and scenic hikes.
The sheer number of options can be overwhelming, from deciding which landmarks to visit and figure out the best places to eat.
Enter the solution: An AI-powered trip planner i.e., our CopilotKit 😉.
To fully understand this tutorial, you need to have a basic understanding of React or Next.js.
Here are the tools required to build the AI-powered trip planner.
An AI copilot is an in-app AI assistant that helps users answer questions and take actions inside an application. It brings LLM intelligence right into your application.
Some common form factors:
CopilotKit is the leading, most robust, and easiest to use open-source framework for building in-app AI copilots. You can have a fully custom AI copilot running in your app within minutes.
{% cta https://git.new/devtoarticle1 %} Checkout CopilotKit ⭐️ {% endcta %}
First, create a Next.js application by running the code snippet below in your terminal:
npx create-next-app@latest ai-trip-planner
You can select your preferred configuration settings. For this tutorial, we'll be using TypeScript and Next.js App Router.
Next, we'll install the Langchain packages and their dependencies.
npm install @langchain/langgraph@^0.0.7
Finally, install the CopilotKit packages. These packages enable us to retrieve data from the React state and add AI copilot to the application.
npm install @copilotkit/react-ui @copilotkit/react-core @copilotkit/runtime
Great, now that we've installed the packages, let's start building the AI-powered trip planner.
First, I will walk you through the process of creating the AI-powered trip planner frontend with static content to define the trip planner user interface.
To get started, go to /[root]/src/app
in your code editor and create a folder called components
. Inside the components folder, create a file named TripPlan.tsx
In the TripPlan.tsx
file, add the following code that defines a React functional component called TripPlan
.
"use client"; // Indicates that this file is a client-side file in a Next.js app
import Link from "next/link"; // Importing Link component from Next.js for navigation
import React, { useState } from "react"; // Importing React and useState hook
// Define the structure of a Todo item with an interface
interface Todo {
time: string;
activity: string;
details: string;
}
// Define the TripPlan component
function TripPlan() {
// Declare a state variable 'tripPlan' to store an array of Todo items, initialized as an empty array
const [tripPlan, setTripPlan] = useState<Todo[]>([]);
return (
<div className="flex flex-col w-full min-h-screen bg-gray-100 dark:bg-gray-800">
{/* Header section */}
<header className="flex items-center h-16 px-4 border-b shrink-0 md:px-6 bg-white dark:bg-gray-900">
{/* Link component for navigation */}
<Link
href="#"
className="flex items-center gap-2 text-lg font-semibold md:text-base"
prefetch={false}>
<span className="sr-only text-gray-500">Trip Plan Dashboard</span>
<h1>AI Trip Plan Generator</h1>
</Link>
</header>
{/* Main content section */}
<main className="flex-1 p-4 md:p-8 lg:p-10">
<div className="container mx-auto p-4">
<h1 className="text-2xl font-bold mb-4">Trip Plan Schedule</h1>
<div className="overflow-x-auto">
{/* Table for displaying the trip plan schedule */}
<table className="min-w-full bg-white border border-gray-300">
<thead>
<tr>
<th className="px-4 py-2 border-b">Time</th>
<th className="px-4 py-2 border-b">Activity</th>
<th className="px-4 py-2 border-b">Details</th>
</tr>
</thead>
<tbody>
{/* Map over the tripPlan state to display each item in the table */}
{tripPlan.map((item, index) => (
<tr
key={index}
className={index % 2 === 0 ? "bg-gray-100" : "bg-white"}>
<td className="px-4 py-2 border-b">{item.time}</td>
<td className="px-4 py-2 border-b">{item.activity}</td>
<td className="px-4 py-2 border-b">{item.details}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</main>
</div>
);
}
export default TripPlan; // Export the TripPlan component as the default export
Next, go to /[root]/src/page.tsx
file, and add the following code that imports the TripPlan
component and defines a functional component named Home
.
import TripPlan from "./components/TripPlan";
export default function Home() {
return <TripPlan />;
}
Finally, run the command npm run dev
on the command line and then navigate to http://localhost:3000/.
Now you should view the AI-powered Trip Planner frontend on your browser, as shown below.
Congratulations! You're now ready to add AI functionalities to the AI-powered Trip Planner.
In this section, you will learn how to add an AI copilot to the AI-powered Trip Planner to create trip plans using CopilotKit.
CopilotKit offers both frontend and backend packages. They enable you to plug into the React states and process application data on the backend using AI agents.
First, let's add the CopilotKit React components to the Trip Planner frontend.
Here, I will walk you through the process of integrating the AI-powered Trip Planner with the CopilotKit frontend to facilitate trip plan creation.
To get started, use the code snippet below to import useCopilotReadable
, and useCopilotAction
, custom hooks at the top of the /src/app/components/TripPlan.tsx
file.
import { useCopilotAction, useCopilotReadable } from "@copilotkit/react-core";
Inside the TripPlan
function, below the state variables, add the following code that uses the useCopilotReadable
hook to add the Trip Plan that will be created as context for the in-app chatbot. The hook makes the Trip Plan readable to the copilot.
useCopilotReadable({
description: "The user's trip plan.",
value: tripPlan,
});
Below the code above, add the following code that uses the useCopilotAction
hook to set up an action called createTripPlan
which will enable the creation of a Trip Plan.
The action takes a parameter called TripDaySchedule
which has the time, activity, and details of a Trip Plan as attributes. It contains a handler function that creates a Trip Plan based on a given prompt.
Inside the handler function, the tripPlan
state is updated with the newly created Trip Plan schedule, as shown below.
// Use the useCopilotAction hook to define a new action
useCopilotAction(
{
name: "createTripPlan", // Name of the action
description: "Create a trip plan following a day schedule format.", // Description of the action
parameters: [
{
name: "TripDaySchedule", // Name of the parameter
type: "object[]", // Type of the parameter (array of objects)
description: "The schedule for the day trip.", // Description of the parameter
attributes: [
{
name: "time", // Name of the attribute
type: "string", // Type of the attribute
description: "The time of the trip day activity.", // Description of the attribute
},
{
name: "activity", // Name of the attribute
type: "string", // Type of the attribute
description:
"The activity to be done in a specific time of the trip day.", // Description of the attribute
},
{
name: "details", // Name of the attribute
type: "string", // Type of the attribute
description: "The details for each activity.", // Description of the attribute
},
],
required: true, // Indicates that this parameter is required
},
],
// Handler function that sets the trip plan using the TripDaySchedule parameter
handler: async ({ TripDaySchedule }) => {
setTripPlan(TripDaySchedule);
},
render: "Creating Your Trip...", // Message to display while the action is being processed
},
[] // Dependency array (empty in this case)
);
After that, go to /[root]/src/app/page.tsx
file and import CopilotKit frontend packages and styles at the top using the code below.
import { CopilotKit } from "@copilotkit/react-core";
import { CopilotSidebar } from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";
Then use CopilotKit
to wrap the CopilotSidebar
and TripPlan
components, as shown below. The CopilotKit
component specifies the URL for CopilotKit's backend endpoint (/api/copilotkit/
) while the CopilotSidebar
renders the in-app chatbot that you can give prompts to create a Trip Plan.
import TripPlan from "./components/TripPlan";
import { CopilotKit } from "@copilotkit/react-core";
import { CopilotSidebar } from "@copilotkit/react-ui";
import "@copilotkit/react-ui/styles.css";
// Export the Home component as the default export
export default function Home() {
return (
// CopilotKit component with a runtimeUrl prop pointing to the API endpoint
<CopilotKit runtimeUrl="/api/copilotkit">
{/* CopilotSidebar component to provide instructions and UI for creating a trip plan */}
<CopilotSidebar
instructions={
"Help the user create a trip plan. Don't add the trip plan to the response."
} // Instructions for the copilot
labels={{
initial:
"Welcome to the Trip Plan app! Describe the trip you want below.",
}} // Labels for the copilot UI
defaultOpen={true} // Sidebar is open by default
clickOutsideToClose={false} // Clicking outside the sidebar does not close it
>
{/* Render the TripPlan component inside the CopilotSidebar */}
<TripPlan />
</CopilotSidebar>
</CopilotKit>
);
}
Now we need to run the development server and navigate to http://localhost:3000.
You should see that the in-app chatbot was integrated into the AI-powered Trip Planner.
Here, I will walk you through the process of integrating the Trip Planner with the CopilotKit backend that handles requests from frontend, and provides function calling and various LLM backends such as GPT.
To get started, create a file called .env.local
in the root directory. Then add the environment variables below in the file that hold your ChatGPT
and Tavily
Search API keys.
OPENAI_API_KEY="Your ChatGPT API key"
TAVILY_API_KEY="Your Tavily Search API key"
OPENAI_MODEL=gpt-4-1106-preview
To get the ChatGPT API key, navigate to https://platform.openai.com/api-keys.
To get the Tavily Search API key, navigate to https://app.tavily.com/home
After that, go to /[root]/src/app
and create a folder called api
. In the api
folder, create a folder called copilotkit
.
In the copilotkit
folder, create a file called research.ts
. Then Navigate to this research.ts gist file, copy the code, and add it to the research.ts
file
Now let's create a file called route.ts
in the /[root]/src/app/api/copilotkit
folder. The file will contain code that sets up a backend functionality to process POST requests. It conditionally includes a "research" action that performs research on a given topic.
// Import the researchWithLangGraph function from the research module
import { researchWithLangGraph } from "./research";
// Import the Action type from the @copilotkit/shared package
import { Action } from "@copilotkit/shared";
// Import the NextRequest type from the next/server module
import { NextRequest } from "next/server";
// Import required modules and classes from the @copilotkit/runtime package
import {
CopilotRuntime,
copilotRuntimeNextJSAppRouterEndpoint,
OpenAIAdapter,
} from "@copilotkit/runtime";
// Define the researchAction object with type Action<any>
const researchAction: Action<any> = {
name: "research", // Name of the action
description:
"Call this function to research on a certain topic. Respect other notes about when to call this function", // Description of the action
parameters: [
{
name: "topic", // Name of the parameter
type: "string", // Type of the parameter, which is a string
description: "The topic to research. 5 characters or longer.", // Description of the parameter
},
],
// Define the handler function for the action, which is asynchronous
handler: async ({ topic }) => {
console.log("Researching topic: ", topic); // Log the topic being researched
return await researchWithLangGraph(topic); // Call the researchWithLangGraph function with the topic and return the result
},
};
// Define the POST function to handle POST requests
export const POST = async (req: NextRequest) => {
const actions: Action<any>[] = []; // Initialize an empty array to hold actions
// Check if the TAVILY_API_KEY environment variable is set and not equal to "NONE"
if (
process.env["TAVILY_API_KEY"] &&
process.env["TAVILY_API_KEY"] !== "NONE"
) {
actions.push(researchAction); // Add the researchAction to the actions array
}
const openaiModel = process.env["OPENAI_MODEL"]; // Get the OpenAI model from the environment variable
// Destructure the handleRequest function from the copilotRuntimeNextJSAppRouterEndpoint function
const { handleRequest } = copilotRuntimeNextJSAppRouterEndpoint({
runtime: new CopilotRuntime({ actions }), // Create a new CopilotRuntime instance with the actions
serviceAdapter: new OpenAIAdapter({ model: openaiModel }), // Create a new OpenAIAdapter instance with the model
endpoint: req.nextUrl.pathname, // Set the endpoint to the current request URL path
});
return handleRequest(req); // Call the handleRequest function with the request and return the result
};
Now go to the in-app chatbot you integrated earlier and give it a prompt like, “Create a trip to London.”
Once it is done generating, you should see the Trip Plan created, as shown below.
Congratulations! You’ve completed the project for this tutorial.
CopilotKit is an incredible tool that allows you to add AI Copilots to your products within minutes. Whether you're interested in AI chatbots and assistants or automating complex tasks, CopilotKit makes it easy.
If you need to build an AI product or integrate an AI tool into your software applications, you should consider CopilotKit.
You can find the source code for this tutorial on GitHub