DEV Community

Cover image for The AI-Powered Trip Planner, šŸ˜» You Can't Live Without āš”
Bonnie for CopilotKit

Posted on • Edited on

The AI-Powered Trip Planner, šŸ˜» You Can't Live Without āš”

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 šŸ˜‰.

Cool!

TL;DR

  • Build the AI-powered trip planner web app using Next.js, TypeScript, and Tailwind CSS.
  • Use CopilotKit to integrate AI functionalities into the trip planner web app.
  • Use Langchain and Tavily to gather information from the web to plan every aspect of your trip efficiently.

Prerequisites

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.

  • LangchainĀ - provides a framework that enables AI agents to search the web, research, and scrape any topic or link.
  • OpenAI APIĀ - provides an API key that enables you to carry out various tasks using ChatGPT models.
  • Tavily AIĀ - a search engine that enables AI agents to conduct research or scrape data and access real-time knowledge within the application.
  • CopilotKitĀ - an open-source copilot framework for building custom AI chatbots, in-app AI agents, and text areas.

What is an AI Copilot?

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:

  • ChatBot: Context-aware in-app chatbots that can take actions in-app šŸ’¬
  • AI autocomplete: AI-poweredĀ textFieldsĀ with context-aware autocomplete & insertions šŸ“
  • CoAgents: In-app AI agents that can dynamically interact with your app & users šŸ¤–

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.

Star CopilotKit

Checkout CopilotKit ā­ļø

Project Set up and Package Installation

First, create a Next.js application by running the code snippet below in your terminal:

npx create-next-app@latest ai-trip-planner
Enter fullscreen mode Exit fullscreen mode

You can select your preferred configuration settings. For this tutorial, we'll be using TypeScript and Next.js App Router.

Code

Next, we'll install the Langchain packages and their dependencies.

npm install @langchain/langgraph@^0.0.7
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Great, now that we've installed the packages, let's start building the AI-powered trip planner.

Building The AI-powered Trip Planner Frontend

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

Enter fullscreen mode Exit fullscreen mode

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 />;
}
Enter fullscreen mode Exit fullscreen mode

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.

Code2

Congratulations! You're now ready to add AI functionalities to the AI-powered Trip Planner.

Integrating AI Functionalities To The Travel Planner Using CopilotKit

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.

Adding CopilotKit 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";
Enter fullscreen mode Exit fullscreen mode

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,
  });
Enter fullscreen mode Exit fullscreen mode

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)
  );
Enter fullscreen mode Exit fullscreen mode

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";
Enter fullscreen mode Exit fullscreen mode

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>
  );
}

Enter fullscreen mode Exit fullscreen mode

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.

code3

Adding CopilotKit Backend to 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
Enter fullscreen mode Exit fullscreen mode

To get the ChatGPT API key, navigate toĀ https://platform.openai.com/api-keys.

Image description

To get the Tavily Search API key, navigate toĀ https://app.tavily.com/home

Code4

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
};
Enter fullscreen mode Exit fullscreen mode

How To Create a Trip Plan

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.

Code5

Congratulations! Youā€™ve completed the project for this tutorial.

Wrapping Up

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

Top comments (11)

Collapse
 
nevodavid profile image
Nevo David

Is there something copilotkit can't do?

Collapse
 
the_greatbonnie profile image
Bonnie

I don't think so.

Collapse
 
nathan_tarbert profile image
Nathan Tarbert

This is a really cool use case using CopilotKit!
Nicely structured tutorial.
I'm going to build this!

Collapse
 
anmolbaranwal profile image
Anmol Baranwal

Whoa! Great work Bonnie šŸ‘

Collapse
 
the_greatbonnie profile image
Bonnie

Thanks, Anmol.

Collapse
 
arshadayvid profile image
David Asaolu

This is amazing, Bonnie.
Thank you for writing this clear guideāš”ļø šŸ„‚

Collapse
 
the_greatbonnie profile image
Bonnie

Happy to hear that, David.

Collapse
 
justinwells21 profile image
justinwells21

I heard about CopilotKit from DevFest!
Super cool!

Collapse
 
the_greatbonnie profile image
Bonnie

Awesome.

Collapse
 
steven0121 profile image
Steven

Awesome!

Collapse
 
the_greatbonnie profile image
Bonnie

Thanks, Steven.