Welcome to the Flight Search AI Assistant project! This application is an AI-powered assistant built with Rust using the Rig library. It allows users to find the cheapest flights between two airports through natural language queries.
- Flight Search AI Assistant
- Natural Language Queries: Interact with the assistant using plain English.
- Flight Search: Find flights between any two airports.
- Customizable: Modify the code to add more features or tools.
- Asynchronous Execution: Built using asynchronous Rust for efficient performance.
Before you begin, ensure you have met the following requirements:
- Rust: Installed Rust programming language. If not, download and install it from rust-lang.org.
- API Keys:
- OpenAI API Key: Sign up and get your key from OpenAI API.
- RapidAPI Key: Sign up and get your key from RapidAPI. We'll use this to access the TripAdvisor Flight Search API.
Follow these instructions to set up and run the project on your local machine.
Open your terminal and run:
git clone https://github.com/0xPlaygrounds/awesome-rig.git
cd flight_search_assistant
Create a .env
file in the root directory of the project to store your API keys:
touch .env
Open the .env
file in your favorite text editor and add the following lines:
OPENAI_API_KEY=your_openai_api_key_here
RAPIDAPI_KEY=your_rapidapi_key_here
Replace your_openai_api_key_here
and your_rapidapi_key_here
with your actual API keys.
Note: Ensure that the .env
file is added to your .gitignore
to prevent committing sensitive information.
Run the following command to download and compile all the dependencies:
cargo build
To build the project, run:
cargo build --release
This will create an optimized build of the application.
Execute the application using:
cargo run
You should see output similar to:
Agent response:
Here are some flight options:
1. **Airline**: Delta Air Lines
- **Flight Number**: DL123
- **Departure**: 2024-11-15T08:00:00-06:00
- **Arrival**: 2024-11-15T10:45:00-05:00
- **Duration**: 2 hours 45 minutes
- **Stops**: Non-stop
- **Price**: 250.00 USD
- **Booking URL**: https://www.tripadvisor.com/CheapFlightsPartnerHandoff...
...
Note: The actual results may vary depending on the API response and the current date.
The agent is programmed to respond to natural language prompts. In main.rs
, the prompt is set as:
let response = agent
.prompt("Find me flights from San Antonio (SAT) to London (LHR) on November 15th 2024.")
.await?;
You can modify this prompt to search for flights between different airports or on different dates.
To change the interaction, open src/main.rs
and edit the prompt
method:
let response = agent
.prompt("Your custom prompt here")
.await?;
For example:
let response = agent
.prompt("I need a flight from New York (JFK) to Tokyo (HND) on December 20th 2024.")
.await?;
After modifying, save the file and run the application again:
cargo run
This is the entry point of the application. It performs the following tasks:
- Initializes the OpenAI client using your API key.
- Builds the AI agent with a preamble and the
FlightSearchTool
. - Sends a prompt to the agent.
- Prints the agent's response.
mod flight_search_tool;
use crate::flight_search_tool::FlightSearchTool;
use dotenv::dotenv;
use rig::completion::Prompt;
use rig::providers::openai;
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
dotenv().ok();
// Initialize the OpenAI client
let openai_client = openai::Client::from_env();
// Build the agent with the FlightSearchTool
let agent = openai_client
.agent("gpt-4")
.preamble("You are a travel assistant that can help users find flights between airports.")
.tool(FlightSearchTool)
.build();
// Send a prompt to the agent
let response = agent
.prompt("Find me flights from San Antonio (SAT) to London (LHR) on November 15th 2024.")
.await?;
// Print the agent's response
println!("Agent response:\n{}", response);
Ok(())
}
This file defines the FlightSearchTool
, which interacts with the TripAdvisor Flight Search API to fetch flight information.
Key components:
- Structs:
FlightSearchArgs
: Represents the input arguments for the flight search.FlightOption
: Represents each flight option returned by the API.
- Error Handling:
FlightSearchError
: Custom error type to handle various errors that might occur.
- Implementation:
- Implements the
Tool
trait forFlightSearchTool
. - Defines the
definition
andcall
methods required by the trait. - The
call
method makes an HTTP request to the API, parses the response, and formats the output.
- Implements the
use chrono::Utc;
use rig::completion::ToolDefinition;
use rig::tool::Tool;
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use std::collections::HashMap;
use std::env;
// Define the arguments for the flight search
#[derive(Deserialize)]
pub struct FlightSearchArgs {
source: String,
destination: String,
date: Option<String>,
// Additional optional parameters...
}
// Define the flight option structure
#[derive(Serialize)]
pub struct FlightOption {
airline: String,
flight_number: String,
departure: String,
arrival: String,
duration: String,
stops: usize,
price: f64,
currency: String,
booking_url: String,
}
// Define custom error types
#[derive(Debug, thiserror::Error)]
pub enum FlightSearchError {
#[error("HTTP request failed: {0}")]
HttpRequestFailed(String),
#[error("Invalid response structure")]
InvalidResponse,
#[error("API error: {0}")]
ApiError(String),
#[error("Missing API key")]
MissingApiKey,
}
// Implement the Tool trait for FlightSearchTool
pub struct FlightSearchTool;
impl Tool for FlightSearchTool {
const NAME: &'static str = "search_flights";
type Args = FlightSearchArgs;
type Output = String;
type Error = FlightSearchError;
// Define the tool
async fn definition(&self, _prompt: String) -> ToolDefinition {
// Tool metadata and parameters
}
// Implement the call method
async fn call(&self, args: Self::Args) -> Result<Self::Output, Self::Error> {
// Fetch API key, set defaults, build query params, make API request
// Parse response and format output
}
}
- Missing API Keys: Ensure that your
.env
file contains the correct API keys and that the keys are valid. - Dependency Errors: Run
cargo update
to update dependencies to their latest versions. - API Errors: Check the API usage limits and ensure that your keys have sufficient permissions.
Contributions are welcome! If you'd like to add features, fix bugs, or improve documentation, feel free to open a pull request.
-
Fork the repository.
-
Create a new branch:
git checkout -b feature/your-feature-name
-
Make your changes.
-
Commit and push:
git commit -m "Description of your changes" git push origin feature/your-feature-name
-
Open a pull request on GitHub.
This project is licensed under the MIT License.
Happy coding! If you have any questions or need further assistance, feel free to open an issue or reach out.