|
|
@ -0,0 +1,993 @@ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cells": [ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 1, |
|
|
|
|
|
|
|
"id": "a07e7793-b8f5-44f4-aded-5562f633271a", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"# imports\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"import os\n", |
|
|
|
|
|
|
|
"import json\n", |
|
|
|
|
|
|
|
"from dotenv import load_dotenv\n", |
|
|
|
|
|
|
|
"from openai import OpenAI\n", |
|
|
|
|
|
|
|
"import gradio as gr\n", |
|
|
|
|
|
|
|
"import base64\n", |
|
|
|
|
|
|
|
"from io import BytesIO\n", |
|
|
|
|
|
|
|
"import tempfile\n", |
|
|
|
|
|
|
|
"import subprocess\n", |
|
|
|
|
|
|
|
"from pydub import AudioSegment\n", |
|
|
|
|
|
|
|
"import time\n", |
|
|
|
|
|
|
|
"import anthropic\n", |
|
|
|
|
|
|
|
"from datetime import datetime, time\n", |
|
|
|
|
|
|
|
"import requests" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 2, |
|
|
|
|
|
|
|
"id": "717ea9d4-1e72-4035-b7c5-5d61da5b8ea3", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"name": "stdout", |
|
|
|
|
|
|
|
"output_type": "stream", |
|
|
|
|
|
|
|
"text": [ |
|
|
|
|
|
|
|
"OpenAI API Key exists and begins sk-proj-\n" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"# Initialization\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"load_dotenv(override=True)\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"openai_api_key = os.getenv('OPENAI_API_KEY')\n", |
|
|
|
|
|
|
|
"open_weather_api_key=os.getenv('open_weather')\n", |
|
|
|
|
|
|
|
"amadeus_api_key=os.getenv('amadeus_key')\n", |
|
|
|
|
|
|
|
"amadeus_secret=os.getenv('amadeus_secret')\n", |
|
|
|
|
|
|
|
"if openai_api_key:\n", |
|
|
|
|
|
|
|
" print(f\"OpenAI API Key exists and begins {openai_api_key[:8]}\")\n", |
|
|
|
|
|
|
|
"else:\n", |
|
|
|
|
|
|
|
" print(\"OpenAI API Key not set\")\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
"gpt_model = \"gpt-4o-mini\"\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"openai = OpenAI()" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 3, |
|
|
|
|
|
|
|
"id": "cc78f4fd-9920-4872-9117-90cd2aeb2a06", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"system_message = \"\"\"You are a helpful assistant. You plan vacations for users in the following chronological manner - \n", |
|
|
|
|
|
|
|
"1) you ask the user (if they have not already confirmed) which destination they want to travel to - beaches or mountains or any other destination \n", |
|
|
|
|
|
|
|
" the user prefers \n", |
|
|
|
|
|
|
|
"2) ask the current location of the user (if they have not already shared), please make sure the user shares the name of an exact city or a nearby city \n", |
|
|
|
|
|
|
|
" with an airport\n", |
|
|
|
|
|
|
|
"3) you list the best nearby vacation destinations (each destination should have an airport or provide the nearest airport option) \n", |
|
|
|
|
|
|
|
"4) you ask them their travel start date for the present year only (if they have not already shared the information) that is which date in 2025 should they start\n", |
|
|
|
|
|
|
|
"5) you make multiple tool calls (use tool check_weather) for finding weather data for each location from the list (from step 3 above) \n", |
|
|
|
|
|
|
|
" by using the location, latitude, longitude, and date_year (as start_date + 1 from the previous year); \n", |
|
|
|
|
|
|
|
" Example, if the start date is June 3rd, 2025, your date_year will become June 4th, 2024. You mandatorily have to share the date with the tool call function.\n", |
|
|
|
|
|
|
|
"6) you shortlist top two destinations with better weather conditions and ask the user to share his final selection (vacation destination) and the number of people \n", |
|
|
|
|
|
|
|
" who will be travelling and also share detailed itenerary for both the options for the user to select. Make sure the start and end destinations remain the same. \n", |
|
|
|
|
|
|
|
" Example, if your onward journey is from bangalore to bali, the trip should end in bali, so that the user can avail the return flight from bali to bangalore.\n", |
|
|
|
|
|
|
|
"7) after the user confirms the final selection and the number of heads(number of people availing the vacation) denoted by \"no\", you confirm \n", |
|
|
|
|
|
|
|
" with the user, before proceeding to call the check_flights tool call to get the exact flight expenses for a return trip. Share the following data \n", |
|
|
|
|
|
|
|
" along with the tool call - origin, destination, departure_date, return_date, number of people, currency (in which the user will be checking the costs). \n", |
|
|
|
|
|
|
|
" Make sure to pass the IATA codes for the origin and destination locations to the check_flights_function tool, as an example, if the user is travelling from \n", |
|
|
|
|
|
|
|
" bangalore to goa, pass the origin and destinations as BLR (not bangalore) and GOI (not GOA). \n", |
|
|
|
|
|
|
|
"8) post obtaining the tool result, analyze, share the flight details and expenses with the user. But don't go ahead and book tickets.\n", |
|
|
|
|
|
|
|
"9) Confirm with the user, the stay options that he/she has in mind - \n", |
|
|
|
|
|
|
|
" a) How many rooms will be needed, then, post confirmation from the user, make the tool call \"check_stays_function\" to check the stay costs by\n", |
|
|
|
|
|
|
|
" supplying the following parameters to the function (You should be having all above parameters by now, in case, anything is missing, ask the user \n", |
|
|
|
|
|
|
|
" before proceeding)-\n", |
|
|
|
|
|
|
|
" i) IATA code of the destination city, example if the user is travelling to goa, it will be GOA\n", |
|
|
|
|
|
|
|
" ii) The check-in date, keep this parameter the same as the start_date for the user\n", |
|
|
|
|
|
|
|
" iii) number of people who will be travelling\n", |
|
|
|
|
|
|
|
" iv) Number of rooms needed\n", |
|
|
|
|
|
|
|
" v) The check-out date, keep this parameter the same as the return date for the user\n", |
|
|
|
|
|
|
|
"11) As the final step, show a detailed summary to the user showing the suggested flight with expenses and the suggested stay with expenses for the travel duration,\n", |
|
|
|
|
|
|
|
" and the user's total expenses for the trip. Example, if the user is travelling from bangalore to goa, and you have already checked the flight costs from step 8\n", |
|
|
|
|
|
|
|
" above as INR 2000, and from step 9 you confirm the stay costs as 1000 per day for a 5-day trip, (this you know from step 6 while making the itenerary), the total\n", |
|
|
|
|
|
|
|
" expenses will be 2000 + (1000x5) = 7000 INR. Display the details to the user. \n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" IMPORTANT NOTE - \n", |
|
|
|
|
|
|
|
" i) You will not proceed with booking any stay or flight tickets after step 11, so never say - \"This is your detailed itenerary, may I proceed to \n", |
|
|
|
|
|
|
|
" book?\", rather say \"Hope you like the itenerary, in case of any changes, let me know and I will help revise the plan.\"\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
"Example usage - \n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"user - plan me a vacation\n", |
|
|
|
|
|
|
|
"assistant - where to? beach or mountain?\n", |
|
|
|
|
|
|
|
"user - beach\n", |
|
|
|
|
|
|
|
"assistant - what is your location?\n", |
|
|
|
|
|
|
|
"user - India\n", |
|
|
|
|
|
|
|
"assistant - At what time of the year do you wish to travel? And which city in India with an airport you will be travelling from?\n", |
|
|
|
|
|
|
|
"user - June 1st, 2025, Bangalore, India\n", |
|
|
|
|
|
|
|
"assistant - top tourist destinations are - goa, gokarna, andaman and nicobar islands, varkala. Do you want me to proceed?\n", |
|
|
|
|
|
|
|
"or do you want to add some suggestions?\n", |
|
|
|
|
|
|
|
"user - please proceed\n", |
|
|
|
|
|
|
|
"assistant - [makes tool calls for each location - goa, gokarna, andaman and nicobar islands, and varkala\n", |
|
|
|
|
|
|
|
"for 2nd June 2024 (previous year), supplying the latitude and longitude data for each, along with the date as start_date+1 and shortlist the \n", |
|
|
|
|
|
|
|
"top two places with the best weather conditions and share \n", |
|
|
|
|
|
|
|
"the details with the user] here you go, based on what you asked for, goa and gokarna seem to be your best options\n", |
|
|
|
|
|
|
|
"considering the weather conditions over a similar period in the previous year. Please let me know your final selection and number of people who will \n", |
|
|
|
|
|
|
|
"be travelling and your preferred currency for the calculations\n", |
|
|
|
|
|
|
|
"user - I will select Goa and 2 people myself and my wife will be travelling. I want to see the costs in INR\n", |
|
|
|
|
|
|
|
"assistant - [makes a final itenerary taking into consideration the information provided by the user. Decides the return date and shares the final details with \n", |
|
|
|
|
|
|
|
"the user and asks him to confirm] here is your final itenerary \"xxx\" start date is June 1st, return date is June 6th. Is this fine or do you want to make few changes \n", |
|
|
|
|
|
|
|
"to the itenerary or start and/or end dates?\n", |
|
|
|
|
|
|
|
"user - please proceed\n", |
|
|
|
|
|
|
|
"assistant - [makes the tool call check_flights_function and passes the following information - Origin: BLR, Destination: GOI, Departure date - 2025-06-01,\n", |
|
|
|
|
|
|
|
"return date - 2025-06-06, no = 2 (number of people), INR (currency). Checks the cost of the return flight ticket as a response from the tool call, analyzes and \n", |
|
|
|
|
|
|
|
"finally showcases the user the flight expenses] Here you go, please find the flight details and the expenses for the same \"xx\". Can you please confirm the number\n", |
|
|
|
|
|
|
|
"of rooms you will be availing so that I can check the hotel details?\n", |
|
|
|
|
|
|
|
"user - sure, it will be 1 room\n", |
|
|
|
|
|
|
|
"assistant - [makes the final tool call check_stays_function to find hotel price details] So the hotel options are \"xxx\" the prices are mostly in the range \"xx\", You final\n", |
|
|
|
|
|
|
|
"itenerary is \"xxx\" with flights booked from bangalore to goa as \"xx\" flight expense - \"xx\", hotel expense \"xx\", total expense \"xx\"\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"Make sure that the travel start date is confirmed by the user and you are passing the travel start date + 1 \n", |
|
|
|
|
|
|
|
"as the \"check_weather\" tool call argument. Also. make sure that in your final answer, do not disclose the exact date again which \n", |
|
|
|
|
|
|
|
"you made the api call. Rather say - Based on the weather conditions over a similar period last year, I will recommend\n", |
|
|
|
|
|
|
|
"location x and y. But make sure you pass the date parameter as start_date + 1 from the previous year (2024) to the check_weather tool call\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"for the check_flights_function tool call, please confirm the currency every time\n", |
|
|
|
|
|
|
|
"for the check_weather tool call, please provide the date_year field each time\n", |
|
|
|
|
|
|
|
"\"\"\"" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 4, |
|
|
|
|
|
|
|
"id": "c919b13a-50b6-4510-8e9d-02cdfd95cb98", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def check_weather(location, latitudes, longitudes, date_year):\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
" print(location)\n", |
|
|
|
|
|
|
|
" print(latitudes)\n", |
|
|
|
|
|
|
|
" print(longitudes)\n", |
|
|
|
|
|
|
|
" print(date_year)\n", |
|
|
|
|
|
|
|
" # if not (len(location) == len(latitudes) == len(longitudes) == len(date_year)):\n", |
|
|
|
|
|
|
|
" # raise ValueError(\"All input lists must have the same length.\")\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" timestamp1=get_unix_timestamp(date_year)\n", |
|
|
|
|
|
|
|
" weather_data = []\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" url = (\n", |
|
|
|
|
|
|
|
" f\"https://api.openweathermap.org/data/3.0/onecall/timemachine?\"\n", |
|
|
|
|
|
|
|
" f\"lat={latitudes}&lon={longitudes}&dt={timestamp1}&appid={open_weather_api_key}&units=metric\"\n", |
|
|
|
|
|
|
|
" )\n", |
|
|
|
|
|
|
|
" print(url)\n", |
|
|
|
|
|
|
|
" try:\n", |
|
|
|
|
|
|
|
" response = requests.get(url)\n", |
|
|
|
|
|
|
|
" response.raise_for_status()\n", |
|
|
|
|
|
|
|
" data = response.json()\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" # Use first available hourly data as representative\n", |
|
|
|
|
|
|
|
" hourly = data.get(\"data\") or data.get(\"hourly\") or []\n", |
|
|
|
|
|
|
|
" if not hourly:\n", |
|
|
|
|
|
|
|
" raise ValueError(\"No hourly data found in response.\")\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" weather_point = hourly[0]\n", |
|
|
|
|
|
|
|
" temperature = weather_point.get(\"temp\")\n", |
|
|
|
|
|
|
|
" weather_desc = weather_point.get(\"weather\", [{}])[0].get(\"description\", \"N/A\")\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" precipitation = 0\n", |
|
|
|
|
|
|
|
" precip_type = \"none\"\n", |
|
|
|
|
|
|
|
" if \"rain\" in weather_point:\n", |
|
|
|
|
|
|
|
" precipitation = weather_point[\"rain\"].get(\"1h\", 0)\n", |
|
|
|
|
|
|
|
" precip_type = \"rain\"\n", |
|
|
|
|
|
|
|
" elif \"snow\" in weather_point:\n", |
|
|
|
|
|
|
|
" precipitation = weather_point[\"snow\"].get(\"1h\", 0)\n", |
|
|
|
|
|
|
|
" precip_type = \"snow\"\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" weather_data.append({\n", |
|
|
|
|
|
|
|
" \"location\": location,\n", |
|
|
|
|
|
|
|
" \"date_year\": timestamp1,\n", |
|
|
|
|
|
|
|
" \"temperature\": temperature,\n", |
|
|
|
|
|
|
|
" \"weather\": weather_desc,\n", |
|
|
|
|
|
|
|
" \"precipitation_type\": precip_type,\n", |
|
|
|
|
|
|
|
" \"precipitation_mm\": precipitation\n", |
|
|
|
|
|
|
|
" })\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" except requests.RequestException as e:\n", |
|
|
|
|
|
|
|
" weather_data.append({\n", |
|
|
|
|
|
|
|
" \"location\": location,\n", |
|
|
|
|
|
|
|
" \"date_year\": timestamp1,\n", |
|
|
|
|
|
|
|
" \"error\": f\"Request failed: {e}\"\n", |
|
|
|
|
|
|
|
" })\n", |
|
|
|
|
|
|
|
" except Exception as e:\n", |
|
|
|
|
|
|
|
" weather_data.append({\n", |
|
|
|
|
|
|
|
" \"location\": location,\n", |
|
|
|
|
|
|
|
" \"date_year\": timestamp1,\n", |
|
|
|
|
|
|
|
" \"error\": f\"Processing error: {e}\"\n", |
|
|
|
|
|
|
|
" })\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" print(weather_data)\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" return weather_data\n" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 5, |
|
|
|
|
|
|
|
"id": "73c4e65a-5080-448a-b3be-0914b10f99f7", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"# call_amadeus(\"BLR\",\"GOI\",\"2025-07-29\",\"2025-08-05\",2,\"INR\")" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 6, |
|
|
|
|
|
|
|
"id": "7115bf68-dc5d-4b54-b5a2-07662e74af5f", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def extract_sorted_flights_by_price_with_baggage_weight(response_json):\n", |
|
|
|
|
|
|
|
" results = []\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
" # Map carrier codes to full names\n", |
|
|
|
|
|
|
|
" carrier_dict = response_json.get(\"dictionaries\", {}).get(\"carriers\", {})\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" for offer in response_json.get(\"data\", []):\n", |
|
|
|
|
|
|
|
" itineraries = offer.get(\"itineraries\", [])\n", |
|
|
|
|
|
|
|
" traveler_pricing = offer.get(\"travelerPricings\", [])[0]\n", |
|
|
|
|
|
|
|
" fare_details = traveler_pricing.get(\"fareDetailsBySegment\", [])\n", |
|
|
|
|
|
|
|
" price = float(offer.get(\"price\", {}).get(\"total\", 0.0))\n", |
|
|
|
|
|
|
|
" currency = offer.get(\"price\", {}).get(\"currency\", \"INR\")\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" outbound_segment = itineraries[0][\"segments\"][0]\n", |
|
|
|
|
|
|
|
" inbound_segment = itineraries[1][\"segments\"][0]\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" outbound_airline = carrier_dict.get(outbound_segment[\"carrierCode\"], outbound_segment[\"carrierCode\"])\n", |
|
|
|
|
|
|
|
" inbound_airline = carrier_dict.get(inbound_segment[\"carrierCode\"], inbound_segment[\"carrierCode\"])\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" # Build baggage weight lookup\n", |
|
|
|
|
|
|
|
" baggage_lookup = {\n", |
|
|
|
|
|
|
|
" fare[\"segmentId\"]: fare.get(\"includedCheckedBags\", {}).get(\"weight\", \"N/A\")\n", |
|
|
|
|
|
|
|
" for fare in fare_details\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" summary = {\n", |
|
|
|
|
|
|
|
" \"Price\": price,\n", |
|
|
|
|
|
|
|
" \"Currency\": currency,\n", |
|
|
|
|
|
|
|
" \"Departure Time\": outbound_segment[\"departure\"][\"at\"],\n", |
|
|
|
|
|
|
|
" \"Return Time\": inbound_segment[\"departure\"][\"at\"],\n", |
|
|
|
|
|
|
|
" \"Departure Airline\": outbound_airline,\n", |
|
|
|
|
|
|
|
" \"Return Airline\": inbound_airline,\n", |
|
|
|
|
|
|
|
" \"Check-in Baggage Weight\": {\n", |
|
|
|
|
|
|
|
" \"Departure\": f'{baggage_lookup.get(outbound_segment[\"id\"], \"N/A\")}kg' if baggage_lookup.get(outbound_segment[\"id\"]) else \"N/A\",\n", |
|
|
|
|
|
|
|
" \"Return\": f'{baggage_lookup.get(inbound_segment[\"id\"], \"N/A\")}kg' if baggage_lookup.get(inbound_segment[\"id\"]) else \"N/A\",\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" results.append(summary)\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" # Sort by price\n", |
|
|
|
|
|
|
|
" sorted_results = sorted(results, key=lambda x: x[\"Price\"])\n", |
|
|
|
|
|
|
|
" return sorted_results\n", |
|
|
|
|
|
|
|
"\n" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 7, |
|
|
|
|
|
|
|
"id": "6929ba76-bf75-490b-adc9-c43bf90ce72d", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"# def get_city_iata_code(city_name):\n", |
|
|
|
|
|
|
|
"# # Step 1: Get access token\n", |
|
|
|
|
|
|
|
"# print(f\"finding iata code for {city_name}\")\n", |
|
|
|
|
|
|
|
"# auth_response = requests.post(\n", |
|
|
|
|
|
|
|
"# \"https://test.api.amadeus.com/v1/security/oauth2/token\",\n", |
|
|
|
|
|
|
|
"# headers={\"Content-Type\": \"application/x-www-form-urlencoded\"},\n", |
|
|
|
|
|
|
|
"# data={\n", |
|
|
|
|
|
|
|
"# \"grant_type\": \"client_credentials\",\n", |
|
|
|
|
|
|
|
"# \"client_id\": amadeus_api_key,\n", |
|
|
|
|
|
|
|
"# \"client_secret\": amadeus_secret\n", |
|
|
|
|
|
|
|
"# }\n", |
|
|
|
|
|
|
|
"# )\n", |
|
|
|
|
|
|
|
"# auth_response.raise_for_status()\n", |
|
|
|
|
|
|
|
"# access_token = auth_response.json()[\"access_token\"]\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"# # Step 2: Search for city IATA code\n", |
|
|
|
|
|
|
|
"# location_response = requests.get(\n", |
|
|
|
|
|
|
|
"# \"https://test.api.amadeus.com/v1/reference-data/locations\",\n", |
|
|
|
|
|
|
|
"# headers={\"Authorization\": f\"Bearer {access_token}\"},\n", |
|
|
|
|
|
|
|
"# params={\"keyword\": city_name, \"subType\": \"CITY\"}\n", |
|
|
|
|
|
|
|
"# )\n", |
|
|
|
|
|
|
|
"# location_response.raise_for_status()\n", |
|
|
|
|
|
|
|
"# data = location_response.json().get(\"data\", [])\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"# if not data:\n", |
|
|
|
|
|
|
|
"# print(f\"No IATA code found for {city_name}\")\n", |
|
|
|
|
|
|
|
"# return None\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"# return data[0][\"iataCode\"]" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 8, |
|
|
|
|
|
|
|
"id": "42a82601-1afa-4a0f-92bc-3cbfdfd9f119", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"# # print(get_city_iata_code(\"bengaluru\"))\n", |
|
|
|
|
|
|
|
"# def lower(s):\n", |
|
|
|
|
|
|
|
"# result = \"\"\n", |
|
|
|
|
|
|
|
"# for char in s:\n", |
|
|
|
|
|
|
|
"# # Check if char is uppercase (ASCII 65–90)\n", |
|
|
|
|
|
|
|
"# if 'A' <= char <= 'Z':\n", |
|
|
|
|
|
|
|
"# # Convert to lowercase by adding 32 to ASCII value\n", |
|
|
|
|
|
|
|
"# result += chr(ord(char) + 32)\n", |
|
|
|
|
|
|
|
"# else:\n", |
|
|
|
|
|
|
|
"# result += char\n", |
|
|
|
|
|
|
|
"# return result" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 9, |
|
|
|
|
|
|
|
"id": "aa6f59ce-9c7d-46ec-945e-aa40ee88e392", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def call_amadeus(origin, destination, departure_date, return_date, no, currency):\n", |
|
|
|
|
|
|
|
" # or1=get_city_iata_code(lower(origin))\n", |
|
|
|
|
|
|
|
" # dest=get_city_iata_code(lower(destination))\n", |
|
|
|
|
|
|
|
" # print(f\"iata codes origin - {or1}, destination - {dest}\")\n", |
|
|
|
|
|
|
|
" or1=origin\n", |
|
|
|
|
|
|
|
" dest=destination\n", |
|
|
|
|
|
|
|
" print(f\"origin is {or1}, destination is {dest}\")\n", |
|
|
|
|
|
|
|
" auth_response = requests.post(\n", |
|
|
|
|
|
|
|
" \"https://test.api.amadeus.com/v1/security/oauth2/token\",\n", |
|
|
|
|
|
|
|
" data={\n", |
|
|
|
|
|
|
|
" \"grant_type\": \"client_credentials\",\n", |
|
|
|
|
|
|
|
" \"client_id\": amadeus_api_key,\n", |
|
|
|
|
|
|
|
" \"client_secret\": amadeus_secret\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
" )\n", |
|
|
|
|
|
|
|
" access_token = auth_response.json()['access_token']\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" # Search flights\n", |
|
|
|
|
|
|
|
" headers = {\"Authorization\": f\"Bearer {access_token}\"}\n", |
|
|
|
|
|
|
|
" params = {\n", |
|
|
|
|
|
|
|
" \"originLocationCode\": or1,\n", |
|
|
|
|
|
|
|
" \"destinationLocationCode\": dest,\n", |
|
|
|
|
|
|
|
" \"departureDate\": departure_date,\n", |
|
|
|
|
|
|
|
" \"returnDate\": return_date,\n", |
|
|
|
|
|
|
|
" \"adults\": 2,\n", |
|
|
|
|
|
|
|
" \"nonStop\": \"false\",\n", |
|
|
|
|
|
|
|
" \"currencyCode\": currency,\n", |
|
|
|
|
|
|
|
" \"max\":4\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
" response = requests.get(\n", |
|
|
|
|
|
|
|
" \"https://test.api.amadeus.com/v2/shopping/flight-offers\",\n", |
|
|
|
|
|
|
|
" headers=headers,\n", |
|
|
|
|
|
|
|
" params=params\n", |
|
|
|
|
|
|
|
" )\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
" # print(response.json())\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" return extract_sorted_flights_by_price_with_baggage_weight(response.json())" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 10, |
|
|
|
|
|
|
|
"id": "973d6078-baf8-4e88-a9f2-529fff15dee6", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def get_access_token():\n", |
|
|
|
|
|
|
|
" url = 'https://test.api.amadeus.com/v1/security/oauth2/token'\n", |
|
|
|
|
|
|
|
" payload = {\n", |
|
|
|
|
|
|
|
" 'grant_type': 'client_credentials',\n", |
|
|
|
|
|
|
|
" 'client_id': amadeus_api_key,\n", |
|
|
|
|
|
|
|
" 'client_secret': amadeus_secret\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" response = requests.post(url, data=payload)\n", |
|
|
|
|
|
|
|
" response.raise_for_status()\n", |
|
|
|
|
|
|
|
" return response.json()['access_token']" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 11, |
|
|
|
|
|
|
|
"id": "ad87f1f3-3fea-437b-9f4e-f1b46e1728fd", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def get_hotel_ids(city_code, radius_km):\n", |
|
|
|
|
|
|
|
" print(\"--------------------checking hotel ids--------------------\")\n", |
|
|
|
|
|
|
|
" token = get_access_token()\n", |
|
|
|
|
|
|
|
" print(f\"Access Token: {token}\")\n", |
|
|
|
|
|
|
|
" url = 'https://test.api.amadeus.com/v1/reference-data/locations/hotels/by-city'\n", |
|
|
|
|
|
|
|
" headers = {\n", |
|
|
|
|
|
|
|
" 'Authorization': f'Bearer {token}'\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
" params = {\n", |
|
|
|
|
|
|
|
" 'cityCode': city_code,\n", |
|
|
|
|
|
|
|
" 'radius': radius_km,\n", |
|
|
|
|
|
|
|
" 'radiusUnit': 'KM',\n", |
|
|
|
|
|
|
|
" # 'amenities': 'SWIMMING_POOL', # Optional filter\n", |
|
|
|
|
|
|
|
" # 'ratings': '3', # Optional filter\n", |
|
|
|
|
|
|
|
" 'hotelSource': 'ALL'\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" response = requests.get(url, headers=headers, params=params)\n", |
|
|
|
|
|
|
|
" response.raise_for_status()\n", |
|
|
|
|
|
|
|
" data = response.json().get('data', [])\n", |
|
|
|
|
|
|
|
" hotel_ids = [hotel['hotelId'] for hotel in data]\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
" print(f\"✅ Found {len(hotel_ids)} hotels in {city_code}\")\n", |
|
|
|
|
|
|
|
" return hotel_ids[:20]\n" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 12, |
|
|
|
|
|
|
|
"id": "7191f8a3-aabc-4f8e-bf11-635ecaf40c5d", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def get_hotel_offers(city_code, check_in_date, no,rooms, check_out_date):\n", |
|
|
|
|
|
|
|
" print(\"---------------inside get hotel offers--------------\")\n", |
|
|
|
|
|
|
|
" hotel_ids=get_hotel_ids(city_code,10)\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
" return get_hotel_offers_by_ids(hotel_ids,check_in_date,no, rooms,check_out_date)\n" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 13, |
|
|
|
|
|
|
|
"id": "e6323979-352c-4fb6-9fe7-216e3613513f", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def get_hotel_offers_by_ids(hotel_ids, check_in_date, adults, rooms, check_out_date):\n", |
|
|
|
|
|
|
|
" print(\"--------------------checking hotel offers based on ids--------------------\")\n", |
|
|
|
|
|
|
|
" token = get_access_token()\n", |
|
|
|
|
|
|
|
" print(f\"Access Token: {token}\")\n", |
|
|
|
|
|
|
|
" url = 'https://test.api.amadeus.com/v3/shopping/hotel-offers'\n", |
|
|
|
|
|
|
|
" headers = {\n", |
|
|
|
|
|
|
|
" 'Authorization': f'Bearer {token}'\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" all_offers = []\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" for hotel_id in hotel_ids:\n", |
|
|
|
|
|
|
|
" params = {\n", |
|
|
|
|
|
|
|
" 'hotelIds': hotel_id,\n", |
|
|
|
|
|
|
|
" # 'adults': adults,\n", |
|
|
|
|
|
|
|
" 'checkInDate': check_in_date,\n", |
|
|
|
|
|
|
|
" 'checkOutDate': check_out_date\n", |
|
|
|
|
|
|
|
" # 'roomQuantity': rooms,\n", |
|
|
|
|
|
|
|
" # 'paymentPolicy': 'NONE',\n", |
|
|
|
|
|
|
|
" # 'includeClosed': 'false',\n", |
|
|
|
|
|
|
|
" # 'bestRateOnly': 'true',\n", |
|
|
|
|
|
|
|
" # 'view': 'FULL',\n", |
|
|
|
|
|
|
|
" # 'sort': 'PRICE'\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" try:\n", |
|
|
|
|
|
|
|
" print(f\"🔍 Checking hotel ID: {hotel_id}\")\n", |
|
|
|
|
|
|
|
" response = requests.get(url, headers=headers, params=params)\n", |
|
|
|
|
|
|
|
" response.raise_for_status()\n", |
|
|
|
|
|
|
|
" offers = response.json()\n", |
|
|
|
|
|
|
|
" if \"data\" in offers and offers[\"data\"]:\n", |
|
|
|
|
|
|
|
" print(f\"✅ Found offers for hotel ID: {hotel_id}\")\n", |
|
|
|
|
|
|
|
" all_offers.extend(offers[\"data\"])\n", |
|
|
|
|
|
|
|
" else:\n", |
|
|
|
|
|
|
|
" print(f\"⚠️ No offers returned for hotel ID: {hotel_id}\")\n", |
|
|
|
|
|
|
|
" except requests.exceptions.HTTPError as e:\n", |
|
|
|
|
|
|
|
" print(f\"❌ HTTPError for hotel ID {hotel_id}: {e}\")\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" if all_offers:\n", |
|
|
|
|
|
|
|
" return json.dumps({\"data\": all_offers}, indent=2)\n", |
|
|
|
|
|
|
|
" else:\n", |
|
|
|
|
|
|
|
" return json.dumps({\"message\": \"No valid hotel offers found.\"}, indent=2)\n" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 14, |
|
|
|
|
|
|
|
"id": "fa82a6d1-cd74-46aa-9b99-c56dc02cddff", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"# print(get_hotel_offers(\"GOI\",\"2025-06-03\",2,1,\"2025-06-08\"))" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 15, |
|
|
|
|
|
|
|
"id": "687e610d-0951-400b-b575-9a83b788bf79", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"check_stays_function = {\n", |
|
|
|
|
|
|
|
" \"name\": \"get_hotel_offers\",\n", |
|
|
|
|
|
|
|
" \"description\": \"Call this tool whenever you need to check the hotel availability and prices for the vacation destination. You need to supply the city_code, check_in_date,\\\n", |
|
|
|
|
|
|
|
" number of heads, and number of rooms\",\n", |
|
|
|
|
|
|
|
" \"parameters\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"object\",\n", |
|
|
|
|
|
|
|
" \"properties\": {\n", |
|
|
|
|
|
|
|
" \"city_code\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"The IATA code for the vacation destination\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"check_in_date\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"the date when the user will be checking into the hotel\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"no\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"the number of heads for which reservation needs to be made, that is, how many members should the reservation be made for\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"rooms\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"The number of rooms to be reserved as confirmed by the user\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"check_out_date\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"the date when the user will be checking out of the hotel\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"required\": [\"city_code\",\"check_in_date\",\"no\",\"rooms\",\"check_out_date\"],\n", |
|
|
|
|
|
|
|
" \"additionalProperties\": False\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
"}" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 16, |
|
|
|
|
|
|
|
"id": "717913a3-aab8-4df7-b9a1-c4bbc649babd", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"check_flights_function = {\n", |
|
|
|
|
|
|
|
" \"name\": \"call_amadeus\",\n", |
|
|
|
|
|
|
|
" \"description\": \"Call this tool whenever you need to check the flight prices and other details for a return \\\n", |
|
|
|
|
|
|
|
" trip from the origin to the destination location (where the user wants to spend his vacation). Make sure that you \\\n", |
|
|
|
|
|
|
|
" supply the origin, destination, departure date, return date, number of tickets, and the \\\n", |
|
|
|
|
|
|
|
" currency in which the user would like to pay. Please note the details provided will be for the return trip and NOT one-way\\\n", |
|
|
|
|
|
|
|
" \",\n", |
|
|
|
|
|
|
|
" \"parameters\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"object\",\n", |
|
|
|
|
|
|
|
" \"properties\": {\n", |
|
|
|
|
|
|
|
" \"origin\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"Origin location for the user - his origin city or a nearby city with an airport\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"destination\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"Destination location for the user - his vacation destination airport or airport \\\n", |
|
|
|
|
|
|
|
" which is nearby to his vacation destination\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"departure_date\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"the start date for the user's vacation\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"return_date\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"the end date/ return date for the user's vacation\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"no\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"the number of tickets to purchase\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"currency\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"the currency in which payment is to be made\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"required\": [\"origin\",\"destination\",\"departure_date\",\"return_date\",\"no\",\"currency\"],\n", |
|
|
|
|
|
|
|
" \"additionalProperties\": False\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
"}" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 17, |
|
|
|
|
|
|
|
"id": "d2628781-6f5e-4ac1-bbe3-2e08aa0aae0d", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"check_weather_function = {\n", |
|
|
|
|
|
|
|
" \"name\": \"check_weather\",\n", |
|
|
|
|
|
|
|
" \"description\": \"Call this tool whenever you need to check the weather of a location for a specific\\\n", |
|
|
|
|
|
|
|
" time from the previous year. The tool will require -\\\n", |
|
|
|
|
|
|
|
" 1) the llm to supply details of one location (based on the category- beaches or mountains or any other category the user selects) \\\n", |
|
|
|
|
|
|
|
" and to which the user might travel to, \\\n", |
|
|
|
|
|
|
|
" 2) the latitude and longitude of that location. \\\n", |
|
|
|
|
|
|
|
" 3) the date_year, which basically is (vacation start date + 1 from previous year.) - this is essentially the date against which the weather conditions are to be \\\n", |
|
|
|
|
|
|
|
" checked. For simplicity, we would keep it as the vacation start date + 1 from the previous year. Example, if the user provides the date as june 3rd, 2025,\\\n", |
|
|
|
|
|
|
|
" date_year will be june 4th, 2024.\\\n", |
|
|
|
|
|
|
|
" This tool call will return a list of weather situations one year ago for the chosen location.\",\n", |
|
|
|
|
|
|
|
" \"parameters\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"object\",\n", |
|
|
|
|
|
|
|
" \"properties\": {\n", |
|
|
|
|
|
|
|
" \"location\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"One of the locations that is near the user's location based on the\\\n", |
|
|
|
|
|
|
|
" category the user selects (beaches or mountains or any other destination category based on the user's choice)\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"lat\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"The latitude of the location\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"long\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"The longitude of the location\",\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"date_year\": {\n", |
|
|
|
|
|
|
|
" \"type\": \"string\",\n", |
|
|
|
|
|
|
|
" \"description\": \"The date of the previous year for which the weather needs to be fetched\",\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
" },\n", |
|
|
|
|
|
|
|
" \"required\": [\"location\",\"lat\",\"long\",\"date_year\"],\n", |
|
|
|
|
|
|
|
" \"additionalProperties\": False\n", |
|
|
|
|
|
|
|
" }\n", |
|
|
|
|
|
|
|
"}" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 18, |
|
|
|
|
|
|
|
"id": "1d5d74a0-9c25-46a4-84ee-1f700bd55fa7", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"# And this is included in a list of tools:\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"tools = [{\"type\": \"function\", \"function\": check_weather_function},\n", |
|
|
|
|
|
|
|
" {\"type\": \"function\", \"function\": check_flights_function},\n", |
|
|
|
|
|
|
|
" {\"type\": \"function\", \"function\": check_stays_function}]" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 19, |
|
|
|
|
|
|
|
"id": "fa18f535-f8a7-4386-b39a-df0f84d23406", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def play_audio(audio_segment):\n", |
|
|
|
|
|
|
|
" temp_dir = tempfile.gettempdir()\n", |
|
|
|
|
|
|
|
" temp_path = os.path.join(temp_dir, \"temp_audio.wav\")\n", |
|
|
|
|
|
|
|
" try:\n", |
|
|
|
|
|
|
|
" audio_segment.export(temp_path, format=\"wav\")\n", |
|
|
|
|
|
|
|
" # time.sleep(3) # Student Dominic found that this was needed. You could also try commenting out to see if not needed on your PC\n", |
|
|
|
|
|
|
|
" subprocess.call([\n", |
|
|
|
|
|
|
|
" \"ffplay\",\n", |
|
|
|
|
|
|
|
" \"-nodisp\",\n", |
|
|
|
|
|
|
|
" \"-autoexit\",\n", |
|
|
|
|
|
|
|
" \"-hide_banner\",\n", |
|
|
|
|
|
|
|
" temp_path\n", |
|
|
|
|
|
|
|
" ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)\n", |
|
|
|
|
|
|
|
" finally:\n", |
|
|
|
|
|
|
|
" try:\n", |
|
|
|
|
|
|
|
" os.remove(temp_path)\n", |
|
|
|
|
|
|
|
" except Exception:\n", |
|
|
|
|
|
|
|
" pass\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
"def talker(message):\n", |
|
|
|
|
|
|
|
" response = openai.audio.speech.create(\n", |
|
|
|
|
|
|
|
" model=\"tts-1\",\n", |
|
|
|
|
|
|
|
" voice=\"alloy\", # Also, try replacing with onyx\n", |
|
|
|
|
|
|
|
" input=message\n", |
|
|
|
|
|
|
|
" )\n", |
|
|
|
|
|
|
|
" audio_stream = BytesIO(response.content)\n", |
|
|
|
|
|
|
|
" audio = AudioSegment.from_file(audio_stream, format=\"mp3\")\n", |
|
|
|
|
|
|
|
" play_audio(audio)\n" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 20, |
|
|
|
|
|
|
|
"id": "b588d711-5f20-4a3a-9422-81a1fda8d5b0", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"# We have to write that function handle_tool_call:\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"def handle_tool_call1(name, args):\n", |
|
|
|
|
|
|
|
" location = args.get('location')\n", |
|
|
|
|
|
|
|
" lat = args.get('lat')\n", |
|
|
|
|
|
|
|
" long = args.get('long')\n", |
|
|
|
|
|
|
|
" date_year = args.get('date_year')\n", |
|
|
|
|
|
|
|
" if name.replace('\"','') == \"check_weather\":\n", |
|
|
|
|
|
|
|
" weather=check_weather(location, lat, long, date_year)\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
" return weather" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 21, |
|
|
|
|
|
|
|
"id": "4eaf63c6-d590-44b8-a508-6e99e314dee1", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"# We have to write that function handle_tool_call:\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"def handle_tool_call2(name, args):\n", |
|
|
|
|
|
|
|
" origin = args.get('origin')\n", |
|
|
|
|
|
|
|
" destination = args.get('destination')\n", |
|
|
|
|
|
|
|
" departure_date = args.get('departure_date')\n", |
|
|
|
|
|
|
|
" return_date = args.get('return_date')\n", |
|
|
|
|
|
|
|
" no = args.get('no')\n", |
|
|
|
|
|
|
|
" currency = args.get('currency')\n", |
|
|
|
|
|
|
|
" if name.replace('\"','') == \"call_amadeus\":\n", |
|
|
|
|
|
|
|
" flights=call_amadeus(origin, destination, departure_date, return_date,no,currency)\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
" return flights" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 22, |
|
|
|
|
|
|
|
"id": "dd85e8dc-6c40-4b6d-b1c3-0efe67093150", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"# We have to write that function handle_tool_call:\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"def handle_tool_call3(name, args):\n", |
|
|
|
|
|
|
|
" city_code = args.get('city_code')\n", |
|
|
|
|
|
|
|
" check_in_date = args.get('check_in_date')\n", |
|
|
|
|
|
|
|
" no = args.get('no')\n", |
|
|
|
|
|
|
|
" rooms = args.get('rooms')\n", |
|
|
|
|
|
|
|
" check_out_date = args.get('check_out_date')\n", |
|
|
|
|
|
|
|
" if name.replace('\"','') == \"get_hotel_offers\":\n", |
|
|
|
|
|
|
|
" hotels=get_hotel_offers(city_code, check_in_date, no, rooms,check_out_date)\n", |
|
|
|
|
|
|
|
" \n", |
|
|
|
|
|
|
|
" return hotels" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 23, |
|
|
|
|
|
|
|
"id": "04a11068-96ab-40eb-9185-1177835a3de7", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def chat_open_ai(history):\n", |
|
|
|
|
|
|
|
" messages = [{\"role\": \"system\", \"content\": system_message}] + history \n", |
|
|
|
|
|
|
|
" response = openai.chat.completions.create(model=gpt_model, messages=messages, tools=tools)\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" tool_responses = []\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" if response.choices[0].finish_reason == \"tool_calls\":\n", |
|
|
|
|
|
|
|
" message = response.choices[0].message\n", |
|
|
|
|
|
|
|
" tool_calls = message.tool_calls # renamed to avoid UnboundLocalError\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" print(f\"tool calls \\n\\n {tool_calls}\")\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" for tool_call in tool_calls:\n", |
|
|
|
|
|
|
|
" tool_id = tool_call.id\n", |
|
|
|
|
|
|
|
" name = tool_call.function.name\n", |
|
|
|
|
|
|
|
" args = json.loads(tool_call.function.arguments)\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" # Call the tool handler\n", |
|
|
|
|
|
|
|
" result = \"\"\n", |
|
|
|
|
|
|
|
" if name == \"check_weather\":\n", |
|
|
|
|
|
|
|
" result = handle_tool_call1(name, args)\n", |
|
|
|
|
|
|
|
" elif name == \"call_amadeus\":\n", |
|
|
|
|
|
|
|
" result = handle_tool_call2(name, args)\n", |
|
|
|
|
|
|
|
" elif name == \"get_hotel_offers\":\n", |
|
|
|
|
|
|
|
" result = handle_tool_call3(name, args)\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" tool_responses.append({\n", |
|
|
|
|
|
|
|
" \"role\": \"tool\",\n", |
|
|
|
|
|
|
|
" \"tool_call_id\": tool_id,\n", |
|
|
|
|
|
|
|
" \"content\": json.dumps(result),\n", |
|
|
|
|
|
|
|
" })\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" print(f\"tool responses {tool_responses}\")\n", |
|
|
|
|
|
|
|
" messages.append(message)\n", |
|
|
|
|
|
|
|
" messages.extend(tool_responses) # important fix here\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" response = openai.chat.completions.create(\n", |
|
|
|
|
|
|
|
" model=gpt_model,\n", |
|
|
|
|
|
|
|
" messages=messages,\n", |
|
|
|
|
|
|
|
" tools=tools\n", |
|
|
|
|
|
|
|
" )\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" reply = response.choices[0].message.content\n", |
|
|
|
|
|
|
|
" # talker(reply)\n", |
|
|
|
|
|
|
|
" history += [{\"role\": \"assistant\", \"content\": reply}]\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" return history\n" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 24, |
|
|
|
|
|
|
|
"id": "a2547bb0-43a5-4b1d-8b9a-95da15a11040", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def chat(history):\n", |
|
|
|
|
|
|
|
" # + [{\"role\": \"user\", \"content\": message}]\n", |
|
|
|
|
|
|
|
" # if Model==\"Open AI\":\n", |
|
|
|
|
|
|
|
" history = chat_open_ai(history)\n", |
|
|
|
|
|
|
|
" # \n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" return history" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 25, |
|
|
|
|
|
|
|
"id": "36e11d99-9281-4efd-a792-dd4fa5935917", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def listen2(history):\n", |
|
|
|
|
|
|
|
" import speech_recognition as sr\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" r = sr.Recognizer()\n", |
|
|
|
|
|
|
|
" with sr.Microphone() as source:\n", |
|
|
|
|
|
|
|
" print(\"Speak now...\")\n", |
|
|
|
|
|
|
|
" audio = r.listen(source, phrase_time_limit=30)\n", |
|
|
|
|
|
|
|
" text=\"\"\n", |
|
|
|
|
|
|
|
" try:\n", |
|
|
|
|
|
|
|
" text = r.recognize_google(audio)\n", |
|
|
|
|
|
|
|
" print(\"You said:\", text)\n", |
|
|
|
|
|
|
|
" except sr.UnknownValueError:\n", |
|
|
|
|
|
|
|
" print(\"Could not understand audio.\")\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" history += [{\"role\":\"user\", \"content\":text}] \n", |
|
|
|
|
|
|
|
" return \"\", history" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 26, |
|
|
|
|
|
|
|
"id": "54e18ba1-78c9-4435-9f12-50fb93ba41fc", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"def get_unix_timestamp(date):\n", |
|
|
|
|
|
|
|
" if date is None:\n", |
|
|
|
|
|
|
|
" return \"Please select a date.\"\n", |
|
|
|
|
|
|
|
" if isinstance(date, str):\n", |
|
|
|
|
|
|
|
" # Convert timestamp (string) to datetime\n", |
|
|
|
|
|
|
|
" date = datetime.strptime(date, \"%Y-%m-%d\").date()\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" dt = datetime.combine(date, time(0, 0)) # Midnight UTC\n", |
|
|
|
|
|
|
|
" unix_timestamp = int(dt.timestamp())\n", |
|
|
|
|
|
|
|
" # url = f\"https://api.openweathermap.org/data/3.0/onecall/timemachine?lat=39.099724&lon=-94.578331&dt={unix_timestamp}&appid={open_weather_api_key}\"\n", |
|
|
|
|
|
|
|
" return unix_timestamp" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": 27, |
|
|
|
|
|
|
|
"id": "133904cf-4d72-4552-84a8-76650f334857", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"name": "stdout", |
|
|
|
|
|
|
|
"output_type": "stream", |
|
|
|
|
|
|
|
"text": [ |
|
|
|
|
|
|
|
"* Running on local URL: http://127.0.0.1:7860\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"To create a public link, set `share=True` in `launch()`.\n" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"data": { |
|
|
|
|
|
|
|
"text/html": [ |
|
|
|
|
|
|
|
"<div><iframe src=\"http://127.0.0.1:7860/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>" |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
"text/plain": [ |
|
|
|
|
|
|
|
"<IPython.core.display.HTML object>" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"output_type": "display_data" |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"data": { |
|
|
|
|
|
|
|
"text/plain": [] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
"execution_count": 27, |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"output_type": "execute_result" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
"source": [ |
|
|
|
|
|
|
|
"with gr.Blocks() as ui:\n", |
|
|
|
|
|
|
|
" with gr.Row():\n", |
|
|
|
|
|
|
|
" chatbot = gr.Chatbot(height=500, type=\"messages\")\n", |
|
|
|
|
|
|
|
" # image_output = gr.Image(height=500)\n", |
|
|
|
|
|
|
|
" # with gr.Row(): \n", |
|
|
|
|
|
|
|
" # date_input = gr.DateTime()\n", |
|
|
|
|
|
|
|
" # output_box = gr.Textbox(label=\"UNIX Timestamp + API URL\", lines=3)\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" with gr.Row():\n", |
|
|
|
|
|
|
|
" entry = gr.Textbox(label=\"Chat with our AI Assistant:\")\n", |
|
|
|
|
|
|
|
" with gr.Row():\n", |
|
|
|
|
|
|
|
" speak = gr.Button(\"click for voice search\") \n", |
|
|
|
|
|
|
|
" with gr.Row():\n", |
|
|
|
|
|
|
|
" clear = gr.Button(\"Clear\")\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" def listen(history):\n", |
|
|
|
|
|
|
|
" message, history=listen2(history)\n", |
|
|
|
|
|
|
|
" return message, history\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" def do_entry(message, history):\n", |
|
|
|
|
|
|
|
" history += [{\"role\":\"user\", \"content\":message}]\n", |
|
|
|
|
|
|
|
" return \"\", history\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
" # entry.submit(get_unix_timestamp, inputs=[date_input], outputs=[output_box])\n", |
|
|
|
|
|
|
|
" entry.submit(do_entry, inputs=[entry, chatbot], outputs=[entry, chatbot]).then(\n", |
|
|
|
|
|
|
|
" # chat, inputs=chatbot, outputs=[chatbot, image_output]\n", |
|
|
|
|
|
|
|
" chat, inputs=[chatbot], outputs=[chatbot]\n", |
|
|
|
|
|
|
|
" )\n", |
|
|
|
|
|
|
|
" speak.click(listen, inputs=[chatbot], outputs=[entry, chatbot]).then(\n", |
|
|
|
|
|
|
|
" chat, inputs=[chatbot], outputs=[chatbot]\n", |
|
|
|
|
|
|
|
" )\n", |
|
|
|
|
|
|
|
" clear.click(lambda: None, inputs=None, outputs=chatbot, queue=False)\n", |
|
|
|
|
|
|
|
"\n", |
|
|
|
|
|
|
|
"ui.launch(inbrowser=True)" |
|
|
|
|
|
|
|
] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": null, |
|
|
|
|
|
|
|
"id": "6507811e-9f98-4b8b-a482-9b0089c60db2", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [] |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
"cell_type": "code", |
|
|
|
|
|
|
|
"execution_count": null, |
|
|
|
|
|
|
|
"id": "f3d3cf51-d2ae-4767-aa04-d8d6feb785bd", |
|
|
|
|
|
|
|
"metadata": {}, |
|
|
|
|
|
|
|
"outputs": [], |
|
|
|
|
|
|
|
"source": [] |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
"metadata": { |
|
|
|
|
|
|
|
"kernelspec": { |
|
|
|
|
|
|
|
"display_name": "Python 3 (ipykernel)", |
|
|
|
|
|
|
|
"language": "python", |
|
|
|
|
|
|
|
"name": "python3" |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
"language_info": { |
|
|
|
|
|
|
|
"codemirror_mode": { |
|
|
|
|
|
|
|
"name": "ipython", |
|
|
|
|
|
|
|
"version": 3 |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
"file_extension": ".py", |
|
|
|
|
|
|
|
"mimetype": "text/x-python", |
|
|
|
|
|
|
|
"name": "python", |
|
|
|
|
|
|
|
"nbconvert_exporter": "python", |
|
|
|
|
|
|
|
"pygments_lexer": "ipython3", |
|
|
|
|
|
|
|
"version": "3.11.11" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
"nbformat": 4, |
|
|
|
|
|
|
|
"nbformat_minor": 5 |
|
|
|
|
|
|
|
} |