This program is an interface that uses Gemini API to parse the user input prompt and convert it to flight queries, calls the Google Flights API on those queries and aggregates the results for you.
See the example prompts in example_prompts/ for inspiration.
- Main features
- How it works (at a high level)
- Video demos
- Setup instructions
- Searching for flights
- Main menu commands
- Token and limits
- File structure
- turns complex, natural language flight queries into Google Flights API calls
- user can specify a range of dates / time / locations / flight constraints in natural language and the program will have Gemini parse the natural language prompt into flight queries for every possible configuration of dates / time / locations / flight constraints.
- can ask the user for clarification if the prompt denoting the flight queries is unclear or contradictory
- allows the user to modify the query parsed by Gemini before calling the Google Flights API on it
The program:
- parses the user's natural language prompt into a set of queries
- each query represents one possible itinerary, which is an order of cities you want to visit for your trip
- if you have multiple trip ideas, put it in the prompt and Gemini will parse them out for you (e.g. separate trips to different destinations, or a trip where you are okay with or without an optional stopover)
- within each query, the following information is extracted from the user prompt (if provided):
- the preferred arrival and departure date and time for each city
- the preferred minimum and maximum number of hours stayed in each city
- the preferred flight constraints for each flight between each city:
- the maximum number of stops
- seat type (i.e. economy, business, etc.)
- the maximum price
- the airlines you want to fly
- the maximum duration of the flight
- the layover constraints:
- the airports you want to do a layover in
- the maximum duration of the layover
- if Gemini has trouble understanding your intent or thinks you made a contradiction in your prompt, it will ask you for clarification
- once Gemini understands your intent and parses your prompt successfully, it will return the queries it thinks it should use to search for flights
- if you want to make modifications to the queries, you can submit another natural language prompt to tell Gemini to modify the queries
- once you are happy with the queries, the program will call the Google Flights API and aggregate all results
- the flight itineraries constructed will be sorted by cheapest price and saved in
saved_flight_itineraries/(NOTE: only the top 1000 cheapest flights will be saved, to make sorting efficient and to save memory).
- get a free Gemini API key here (read more in the docs)
- ensure you have a working Python environment with version at least
3.10.10 - clone this repo and run
pip install -r requirements.txt - open a terminal window and run
python main.py - set your API key by typing
/api_keyand copy and pasting your API key here (this will be saved for future sessions so you only have to do this once)
These are the commands you can run in the main menu of the program:
/help: to see all main menu commands/api_key: to set api key/model: to set model type (defaults togemini-2.5-flash)/top_n: to set how many flight itineraries to display (defaults to20)/debug: to toggle debug on/off (defaults to off). If on, Gemini conversations will be saved to thelogs/folder. NOTE: toggling on or off will reset the chat history./prompt: to begin typing a prompt denoting a flight query/exit: to exit the program
From the main menu, type /prompt and press Enter. Then type your flight query (multi-line input is accepted). When you're done entering your query, enter /submit in a newline and press Enter.
NOTE: Pay special attention to the constraints added to your flight query that were parsed from your prompt by Gemini. If there are too many constraints or they are too restrictive, you may not find any valid flights. I would err on the side of relaxing the constraints a bit more (especially for the min/max time spent in the city; e.g. you may intend to stay for 2 nights at a city but that may not amount to a full 48 hours if you arrive at night and leave in the morning, so better to set the min time spent in the city to 1 day instead of 2 days), or at least don't put too many constraints for each individual city you are traveling to and individual flight you're taking. Empirically, I find that setting the min/max time spent in a city is too restrictive and I usually would just set a departure date range for each city instead.
NOTE: Sometimes the Google flight API is flaky and may return 0 results when in reality, there are valid results. In this case, it won't hurt to retry the query again. Once you're back in the main menu, you can simply type /prompt and type something like "I want to retry the flight query again" and Gemini should return the same query where you can type /search to try using the same query to search for flights.
Some things you can specify in the flight query prompt to filter for:
- which cities you want to visit and in what order
- you can specify separate related/unrelated flight queries (e.g. London -> Toronto, London -> NYC, London -> NYC -> Toronto, Singapore -> Hong Kong -> Taiwan) within the same prompt
- for each individual city:
- minimum and maximum time spent in a city (hours, days, weeks, months, etc.)
- what dates you want to arrive in / depart from the city by
- what time of the day you want to arrive in / depart from the city by
- flight constraints for your flight departing from this city:
- the maximum number of stops in the flight (i.e. non-stop, at most 1 stop, at most 2 stops, any number of stops)
- if unspecified, this defaults to any number of stops
- seat type (e.g. economy, business)
- if unspecified, this defaults to economy
- maximum price of the flight
- airlines whitelist; i.e. the set of airlines that you want to fly, and no other airlines would be valid
- maximum duration of the flight
- maximum layover duration
- layover airport whitelist; i.e. the set of airports you want to layover at, and no other airports would be valid
- the maximum number of stops in the flight (i.e. non-stop, at most 1 stop, at most 2 stops, any number of stops)
As of November 23rd, 2025, the free Gemini API key has a maximum tokens-per-minute (TPM) of 125000 for Gemini 2.5 Pro and 250000 for Gemini 2.5 Flash and Gemini 2.5 Flash-Lite. Since the prompt used in this program is around 120000 tokens, this will allow the user to send a prompt to Gemini once per minute for Gemini 2.5 Pro and twice a minute for Gemini 2.5 Flash and Gemini 2.5 Flash-Lite. Keep in mind that the longer a conversation continues with Gemini, the higher your token usage will be. If you get a rate limit error, simply wait a minute and retry via the /retry command.
You could also try Gemini 2.0 which has a 1 million TPM limit, but Gemini 2.0 models do not have thinking (although perhaps not a lot of thinking is needed to just parse the user intent into flight query constraints). If you find yourself being rate limited too often, you can switch the model by executing the /model command in the main menu of the program.
You can see the number of tokens used by the prompt sent to Gemini in the files in api_call_history/.
See more details on the rate limits here.
main.py: callsorchestratorpyto run the main program loop that interacts with the user.orchestrator.py: acts as the interface between the user and the flight query / itinerary tools. Calls Gemini API to parse the intent of the user's prompt, calls the Google Flights API on the parsed queries and then calls flight itinerary tools to generate all possible flight itineraries and aggregates the results.city.py: contains dataclasses for cities and city ranges, which contain date and time constraints as well as other travel constraints for each city in the trip. These city constraints make up a flight query.flight_info.py: contains a dataclass for flight info and functions to search for flights given a flight query.flight_itinerary.py: contains dataclasses to store flight itineraries, which are comprised of flight info instances fromflight_info.py. Also contains functions to find all possible flight itineraries and aggregate the results, given all possible flights for some trip.flight_hash.py: utility functions for hashing flight info objects.model.py: class to call the Gemini API on a user prompt.prompts.py: contains prompts that show the dataclass structure and fields of the city ranges class incity.pyso that Gemini knows in what format to parse the user prompt into. This city ranges class is then used as a query that the Google Flights API can be called on.utils.py: Python code execution class as well as miscellaneous utility functions.datetime_range.py: dataclasses for denoting datetime, date and time ranges for city constraints.iata_codes.json: maps airport IATA codes to the corresponding city / location. This is used to figure out the name of the city / location that corresponds to the airport we are traveling to/from; i.e. the city / location name is more user-friendly to print out for them to view than the airport codes. This mapping was derived fromiata_codes.pdfiata_codes.pdf: the original.pdfthat maps the IATA airport codes to the corresponding city / location.iata_codes_link.txt: contains the URL where I downloadediata_codes.pdffrom.saved_flight_itineraries/: saved flight itineraries in the form of.tsvfiles that are a result of flight query searches. NOTE: only the top 1000 cheapest flights will be saved, to make sorting efficient and to save memory.api_call_history/: keeps track of Gemini API requests and their token count.logs/: logs user input into Gemini API as well as Gemini's output, for debugging purposes. To turn on logging, toggle debugging on by executing the/debugcommand in the main menu of the program.example_prompts/: example flight query prompts.video_demos/: video demos of interacting with the program, converting the user prompt to flight queries and using them to search for flights.requirements.txt: Python dependencies file.


