{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### libraries import"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true,
    "id": "oOnNfKjX4IAV"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/homebrew/Caskroom/miniconda/base/envs/llm/lib/python3.11/site-packages/transformers/utils/generic.py:441: UserWarning: torch.utils._pytree._register_pytree_node is deprecated. Please use torch.utils._pytree.register_pytree_node instead.\n",
      "  _torch_pytree._register_pytree_node(\n",
      "/opt/homebrew/Caskroom/miniconda/base/envs/llm/lib/python3.11/site-packages/transformers/utils/generic.py:309: UserWarning: torch.utils._pytree._register_pytree_node is deprecated. Please use torch.utils._pytree.register_pytree_node instead.\n",
      "  _torch_pytree._register_pytree_node(\n",
      "/opt/homebrew/Caskroom/miniconda/base/envs/llm/lib/python3.11/site-packages/transformers/utils/generic.py:309: UserWarning: torch.utils._pytree._register_pytree_node is deprecated. Please use torch.utils._pytree.register_pytree_node instead.\n",
      "  _torch_pytree._register_pytree_node(\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "\n",
    "#gradio interface\n",
    "import gradio as gr\n",
    "\n",
    "from transformers import AutoModelForCausalLM,AutoTokenizer\n",
    "import torch\n",
    "\n",
    "#STT (speech to text)\n",
    "from transformers import WhisperProcessor, WhisperForConditionalGeneration\n",
    "import librosa\n",
    "\n",
    "#TTS (text to speech)\n",
    "import torch\n",
    "from TTS.api import TTS\n",
    "from IPython.display import Audio\n",
    "\n",
    "#json request for APIs\n",
    "import requests\n",
    "import json\n",
    "\n",
    "#regular expressions\n",
    "import re\n",
    "\n",
    "#langchain and function calling\n",
    "from typing import List, Literal, Union\n",
    "import requests\n",
    "from functools import partial\n",
    "import math\n",
    "\n",
    "\n",
    "#langchain, not used anymore since I had to find another way fast to stop using the endpoint, but could be interesting to reuse \n",
    "from langchain.tools.base import StructuredTool\n",
    "from langchain.agents import (\n",
    "    Tool,\n",
    "    AgentExecutor,\n",
    "    LLMSingleActionAgent,\n",
    "    AgentOutputParser,\n",
    ")\n",
    "from langchain.schema import AgentAction, AgentFinish, OutputParserException\n",
    "from langchain.prompts import StringPromptTemplate\n",
    "from langchain.llms import HuggingFaceTextGenInference\n",
    "from langchain.chains import LLMChain\n",
    "\n",
    "\n",
    "\n",
    "from datetime import datetime, timedelta, timezone\n",
    "from transformers import pipeline\n",
    "import inspect"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from apis import *"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "os.environ[\"COQUI_TOS_AGREED\"] = \"1\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Models loads"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "preprocessor_config.json: 100%|██████████| 185k/185k [00:00<00:00, 94.3MB/s]\n",
      "tokenizer_config.json: 100%|██████████| 283k/283k [00:00<00:00, 1.05MB/s]\n",
      "vocab.json: 100%|██████████| 836k/836k [00:00<00:00, 3.03MB/s]\n",
      "tokenizer.json: 100%|██████████| 2.48M/2.48M [00:00<00:00, 50.6MB/s]\n",
      "merges.txt: 100%|██████████| 494k/494k [00:00<00:00, 28.8MB/s]\n",
      "normalizer.json: 100%|██████████| 52.7k/52.7k [00:00<00:00, 67.8MB/s]\n",
      "added_tokens.json: 100%|██████████| 34.6k/34.6k [00:00<00:00, 38.7MB/s]\n",
      "special_tokens_map.json: 100%|██████████| 2.19k/2.19k [00:00<00:00, 8.88MB/s]\n",
      "Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.\n",
      "config.json: 100%|██████████| 1.97k/1.97k [00:00<00:00, 4.46MB/s]\n",
      "model.safetensors: 100%|██████████| 967M/967M [00:12<00:00, 74.9MB/s] \n",
      "generation_config.json: 100%|██████████| 3.87k/3.87k [00:00<00:00, 39.0MB/s]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " > Downloading model to /Users/sasan.jafarnejad/Library/Application Support/tts/tts_models--multilingual--multi-dataset--xtts_v1.1\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 1.87G/1.87G [00:24<00:00, 75.6MiB/s]\n",
      "100%|██████████| 4.70k/4.70k [00:00<00:00, 17.9kiB/s]\n",
      "100%|██████████| 294k/294k [00:00<00:00, 1.23MiB/s]\n",
      "/opt/homebrew/Caskroom/miniconda/base/envs/llm/lib/python3.11/site-packages/transformers/utils/generic.py:309: UserWarning: torch.utils._pytree._register_pytree_node is deprecated. Please use torch.utils._pytree.register_pytree_node instead.\n",
      "  _torch_pytree._register_pytree_node(\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " > Model's license - CPML\n",
      " > Check https://coqui.ai/cpml.txt for more info.\n",
      " > Using model: xtts\n"
     ]
    }
   ],
   "source": [
    "# load model and processor for speech-to-text\n",
    "processor = WhisperProcessor.from_pretrained(\"openai/whisper-small\")\n",
    "modelw = WhisperForConditionalGeneration.from_pretrained(\"openai/whisper-small\")\n",
    "modelw.config.forced_decoder_ids = None\n",
    "\n",
    "#load model for text to speech\n",
    "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
    "tts = TTS(\"tts_models/multilingual/multi-dataset/xtts_v1.1\").to(device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true,
    "id": "JNALTDb0LT90"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "config.json: 100%|██████████| 1.42k/1.42k [00:00<00:00, 3.24MB/s]\n",
      "model.safetensors: 100%|██████████| 1.11G/1.11G [00:13<00:00, 79.5MB/s]\n",
      "tokenizer_config.json: 100%|██████████| 502/502 [00:00<00:00, 5.01MB/s]\n",
      "sentencepiece.bpe.model: 100%|██████████| 5.07M/5.07M [00:00<00:00, 78.4MB/s]\n",
      "tokenizer.json: 100%|██████████| 9.08M/9.08M [00:00<00:00, 61.5MB/s]\n",
      "special_tokens_map.json: 100%|██████████| 239/239 [00:00<00:00, 372kB/s]\n"
     ]
    }
   ],
   "source": [
    "#load model language recognition\n",
    "model_ckpt = \"papluca/xlm-roberta-base-language-detection\"\n",
    "pipe_language = pipeline(\"text-classification\", model=model_ckpt)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Loading checkpoint shards: 100%|██████████| 2/2 [00:01<00:00,  1.44it/s]\n"
     ]
    }
   ],
   "source": [
    "#load model llama2\n",
    "mn = 'stabilityai/StableBeluga-7B' #mn = \"TheBloke/Llama-2-7b-Chat-GPTQ\" --> other possibility \n",
    "# model = AutoModelForCausalLM.from_pretrained(mn, device_map=0, load_in_4bit=True) #torch_dtype=torch.float16\n",
    "model = AutoModelForCausalLM.from_pretrained(mn, device_map=0) #torch_dtype=torch.float16\n",
    "# tokr = AutoTokenizer.from_pretrained(mn, load_in_4bit=True) #tokenizer\n",
    "tokr = AutoTokenizer.from_pretrained(mn) #tokenizer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.\n",
      "Loading checkpoint shards: 100%|██████████| 3/3 [00:10<00:00,  3.39s/it]\n"
     ]
    }
   ],
   "source": [
    "#NexusRaven for function calling\n",
    "model_id = \"Nexusflow/NexusRaven-13B\"\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
    "modelNexus = AutoModelForCausalLM.from_pretrained(model_id, device_map=0, load_in_4bit=True)\n",
    "pipe = pipeline(\"text-generation\", model=modelNexus, tokenizer = tokenizer)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Function calling with NexusRaven "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# load api key from .env file\n",
    "# weather api and tomtom api key\n",
    "from dotenv import load_dotenv\n",
    "load_dotenv()\n",
    "WHEATHER_API_KEY = os.getenv(\"WEATHER_API_KEY\")\n",
    "TOMTOM_KEY = os.getenv(\"TOMTOM_API_KEY\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "#FUNCTION CALLING \n",
    "\n",
    "##########################################################\n",
    "# Step 1: Define the functions you want to articulate. ###\n",
    "##########################################################\n",
    "\n",
    "# apis.py\n",
    "\n",
    "\n",
    "#############################################################\n",
    "# Step 2: Let's define some utils for building the prompt ###\n",
    "#############################################################\n",
    "\n",
    "\n",
    "def format_functions_for_prompt(*functions):\n",
    "    formatted_functions = []\n",
    "    for func in functions:\n",
    "        source_code = inspect.getsource(func)\n",
    "        docstring = inspect.getdoc(func)\n",
    "        formatted_functions.append(\n",
    "            f\"OPTION:\\n<func_start>{source_code}<func_end>\\n<docstring_start>\\n{docstring}\\n<docstring_end>\"\n",
    "        )\n",
    "    return \"\\n\".join(formatted_functions)\n",
    "\n",
    "\n",
    "##############################\n",
    "# Step 3: Construct Prompt ###\n",
    "##############################\n",
    "\n",
    "\n",
    "def construct_prompt(user_query: str, context):\n",
    "    formatted_prompt = format_functions_for_prompt(get_weather, find_points_of_interest, find_route, get_forecast, search_along_route)\n",
    "    formatted_prompt += f'\\n\\nContext : {context}'\n",
    "    formatted_prompt += f\"\\n\\nUser Query: Question: {user_query}\\n\"\n",
    "\n",
    "    prompt = (\n",
    "        \"<human>:\\n\"\n",
    "        + formatted_prompt\n",
    "        + \"Please pick a function from the above options that best answers the user query and fill in the appropriate arguments.<human_end>\"\n",
    "    )\n",
    "    return prompt\n",
    "\n",
    "#######################################\n",
    "# Step 4: Execute the function call ###\n",
    "#######################################\n",
    "\n",
    "\n",
    "def execute_function_call(model_output):\n",
    "    # Ignore everything after \"Reflection\" since that is not essential.\n",
    "    function_call = (\n",
    "        model_output[0][\"generated_text\"]\n",
    "        .strip()\n",
    "        .split(\"\\n\")[1]\n",
    "        .replace(\"Initial Answer:\", \"\")\n",
    "        .strip()\n",
    "    )\n",
    "\n",
    "    try:\n",
    "        return eval(function_call)\n",
    "    except Exception as e:\n",
    "        return str(e)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# convert bytes to megabytes\n",
    "def get_cuda_usage(): return round(torch.cuda.memory_allocated(\"cuda:0\")/1024/1024,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "before everything: 13728.13\n",
      "after creating prompt: 13728.13\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/opt/conda/lib/python3.10/site-packages/bitsandbytes/nn/modules.py:391: UserWarning: Input type into Linear4bit is torch.float16, but bnb_4bit_compute_dtype=torch.float32 (default). This will lead to slow inference or training speed.\n",
      "  warnings.warn('Input type into Linear4bit is torch.float16, but bnb_4bit_compute_dtype=torch.float32 (default). This will lead to slow inference or training speed.')\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " \n",
      " Thought: The purpose of the def search_along_route(latitude_depart, longitude_depart, city_destination, type_of_poi) is to return some of the closest points of interest along the route from the depart point, specified by its coordinates and a city destination.\n",
      "Initial Answer: search_along_route(49.5999681, 6.1342493, 'Thionville','restaurant')\n",
      "Reflection: The search_along_route function takes in four arguments: latitude_depart, longitude_depart, city_destination, and type_of_poi.\n",
      "\n",
      "The user has asked what restaurants are there on the road from Luxembourg Gare, which coordinates are lat 49.5999681, lon 6.1342493, to Thionville.\n",
      "\n",
      "The call provided is search_along_route(49.5999681, 6.1342493, 'Thionville','restaurant').\n",
      "\n",
      "The call can be improved because the function requires the latitude and longitude of the depart point, as well as the city destination. The call provided only provides the latitude and longitude of the depart point, and the city destination.\n",
      "\n",
      "The correct call would be\n"
     ]
    }
   ],
   "source": [
    "# might be deleted\n",
    "# Compute a Simple equation\n",
    "print(f\"before everything: {get_cuda_usage()}\")\n",
    "prompt = construct_prompt(\"What restaurants are there on the road from Luxembourg Gare, which coordinates are lat 49.5999681, lon 6.1342493, to Thionville?\", \"\")\n",
    "print(f\"after creating prompt: {get_cuda_usage()}\")\n",
    "model_output = pipe(\n",
    "    prompt, do_sample=False, max_new_tokens=300, return_full_text=False\n",
    "    )\n",
    "print(model_output[0][\"generated_text\"])\n",
    "#execute_function_call(pipe(construct_prompt(\"Is it raining in Belval, ?\"), do_sample=False, max_new_tokens=300, return_full_text=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "creating the pipe of model output: 13736.26\n",
      "49.3579272\n",
      "after execute function call: 13736.26\n",
      "after garbage collect and empty_cache: 13736.26\n"
     ]
    }
   ],
   "source": [
    "print(f\"creating the pipe of model output: {get_cuda_usage()}\")\n",
    "result = execute_function_call(model_output)\n",
    "print(f\"after execute function call: {get_cuda_usage()}\")\n",
    "del model_output\n",
    "import gc         # garbage collect library\n",
    "gc.collect()\n",
    "torch.cuda.empty_cache() \n",
    "print(f\"after garbage collect and empty_cache: {get_cuda_usage()}\")\n",
    "#print(\"Model Output:\", model_output)\n",
    "# print(\"Execution Result:\", result)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## functions to process the anwser and the question"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "#generation of text with Stable beluga \n",
    "def gen(p, maxlen=15, sample=True):\n",
    "    toks = tokr(p, return_tensors=\"pt\")\n",
    "    res = model.generate(**toks.to(\"cuda\"), max_new_tokens=maxlen, do_sample=sample).to('cpu')\n",
    "    return tokr.batch_decode(res)\n",
    "\n",
    "#to have a prompt corresponding to the specific format required by the fine-tuned model Stable Beluga\n",
    "def mk_prompt(user, syst=\"### System:\\nYou are a useful AI assistant in a car, that follows instructions extremely well. Help as much as you can. Answer questions concisely and do not mention what you base your reply on.\\n\\n\"): return f\"{syst}### User: {user}\\n\\n### Assistant:\\n\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "id": "yAJI0WyOLE8G"
   },
   "outputs": [],
   "source": [
    "def car_answer_only(complete_answer, general_context):\n",
    "    \"\"\"returns only the AI assistant answer, without all context, to reply to the user\"\"\"\n",
    "    pattern = r\"Assistant:\\\\n(.*)(</s>|[.!?](\\s|$))\" #pattern = r\"Assistant:\\\\n(.*?)</s>\"\n",
    "\n",
    "    match = re.search(pattern, complete_answer, re.DOTALL)\n",
    "\n",
    "    if match:\n",
    "        # Extracting the text\n",
    "        model_answer = match.group(1)\n",
    "        #print(complete_answer)\n",
    "    else:\n",
    "        #print(complete_answer)\n",
    "        model_answer = \"There has been an error with the generated response.\" \n",
    "\n",
    "    general_context +=  model_answer\n",
    "    return (model_answer, general_context)\n",
    "#print(model_answer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "id": "ViCEgogaENNV"
   },
   "outputs": [],
   "source": [
    "def FnAnswer(general_context, ques, place, time, delete_history, state):\n",
    "    \"\"\"function to manage the two different llms (function calling and basic answer) and call them one after the other\"\"\"\n",
    "    # Initialize state if it is None\n",
    "    if delete_history == \"Yes\":\n",
    "        state = None\n",
    "    if state is None:\n",
    "        conv_context = []\n",
    "        conv_context.append(general_context)\n",
    "        state = {}\n",
    "        state['context'] = conv_context\n",
    "        state['number'] = 0\n",
    "        state['last_question'] = \"\"\n",
    "        \n",
    "    if type(ques) != str: \n",
    "        ques = ques[0]\n",
    "        \n",
    "    place = definePlace(place) #which on the predefined places it is\n",
    "    \n",
    "    formatted_context = '\\n'.join(state['context'])\n",
    "        \n",
    "    #updated at every question\n",
    "    general_context = f\"\"\"\n",
    "    Recent conversation history: '{formatted_context}' (If empty, this indicates the beginning of the conversation).\n",
    "\n",
    "    Previous question from the user: '{state['last_question']}' (This may or may not be related to the current question).\n",
    "\n",
    "    User information: The user is inside a car in {place[0]}, with latitude {place[1]} and longitude {place[2]}. The user is mobile and can drive to different destinations. It is currently {time}\n",
    "\n",
    "    \"\"\"\n",
    "    #first llm call (function calling model, NexusRaven)\n",
    "    model_output= pipe(construct_prompt(ques, general_context), do_sample=False, max_new_tokens=300, return_full_text=False)\n",
    "    call = execute_function_call(model_output) #call variable is formatted to as a call to a specific function with the required parameters\n",
    "    print(call)\n",
    "    #this is what will erase the model_output from the GPU memory to free up space\n",
    "    del model_output\n",
    "    import gc         # garbage collect library\n",
    "    gc.collect()\n",
    "    torch.cuda.empty_cache() \n",
    "        \n",
    "    #updated at every question\n",
    "    general_context += f'This information might be of help, use if it seems relevant, and ignore if not relevant to reply to the user: \"{call}\". '\n",
    "    \n",
    "    #question formatted for the StableBeluga llm (second llm), using the output of the first llm as context in general_context\n",
    "    question=f\"\"\"Reply to the user and answer any question with the help of the provided context.\n",
    "\n",
    "    ## Context\n",
    "\n",
    "    {general_context} .\n",
    "\n",
    "    ## Question\n",
    "\n",
    "    {ques}\"\"\"\n",
    "\n",
    "    complete_answer = str(gen(mk_prompt(question), 100)) #answer generation with StableBeluga (2nd llm)\n",
    "\n",
    "    model_answer, general_context= car_answer_only(complete_answer, general_context) #to retrieve only the car answer \n",
    "    \n",
    "    language = pipe_language(model_answer, top_k=1, truncation=True)[0]['label'] #detect the language of the answer, to modify the text-to-speech consequently\n",
    "    \n",
    "    state['last_question'] = ques #add the current question as 'last question' for the next question's context\n",
    "    \n",
    "    state['number']= state['number'] + 1  #adds 1 to the number of interactions with the car\n",
    "\n",
    "    state['context'].append(str(state['number']) + '. User question: '+ ques + ', Model answer: ' + model_answer) #modifies the context\n",
    "    \n",
    "    #print(\"contexte : \" + '\\n'.join(state['context']))\n",
    "    \n",
    "    if len(state['context'])>5: #6 questions maximum in the context to avoid having too many information\n",
    "        state['context'] = state['context'][1:]\n",
    "\n",
    "    return model_answer, state['context'], state, language"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "id": "9WQlYePVLrTN"
   },
   "outputs": [],
   "source": [
    "def transcript(general_context, link_to_audio, voice, place, time, delete_history, state):\n",
    "    \"\"\"this function manages speech-to-text to input Fnanswer function and text-to-speech with the Fnanswer output\"\"\"\n",
    "    # load audio from a specific path\n",
    "    audio_path = link_to_audio\n",
    "    audio_array, sampling_rate = librosa.load(link_to_audio, sr=16000)  # \"sr=16000\" ensures that the sampling rate is as required\n",
    "\n",
    "\n",
    "    # process the audio array\n",
    "    input_features = processor(audio_array, sampling_rate, return_tensors=\"pt\").input_features\n",
    "\n",
    "\n",
    "    predicted_ids = modelw.generate(input_features)\n",
    "\n",
    "    transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True)\n",
    "\n",
    "    quest_processing = FnAnswer(general_context, transcription, place, time, delete_history, state)\n",
    "    \n",
    "    state=quest_processing[2]\n",
    "    \n",
    "    print(\"langue \" + quest_processing[3])\n",
    "\n",
    "    tts.tts_to_file(text= str(quest_processing[0]),\n",
    "                file_path=\"output.wav\",\n",
    "                speaker_wav=f'Audio_Files/{voice}.wav',\n",
    "                language=quest_processing[3],\n",
    "                emotion = \"angry\")\n",
    "\n",
    "    audio_path = \"output.wav\"\n",
    "    return audio_path, state['context'], state"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "def definePlace(place):\n",
    "    if(place == 'Luxembourg Gare, Luxembourg'):\n",
    "        return('Luxembourg Gare', '49.5999681', '6.1342493' )\n",
    "    elif (place =='Kirchberg Campus, Kirchberg'):\n",
    "        return('Kirchberg Campus, Luxembourg', '49.62571206478235', '6.160082636815114')\n",
    "    elif (place =='Belval Campus, Belval'):\n",
    "        return('Belval-Université, Esch-sur-Alzette', '49.499531', '5.9462903')\n",
    "    elif (place =='Eiffel Tower, Paris'):\n",
    "        return('Eiffel Tower, Paris', '48.8582599', '2.2945006')\n",
    "    elif (place=='Thionville, France'):\n",
    "        return('Thionville, France', '49.357927', '6.167587')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Interfaces (text and audio)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Running on local URL:  http://0.0.0.0:7860\n",
      "\n",
      "Could not create share link. Please check your internet connection or our status page: https://status.gradio.app.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2024/03/15 19:02:04 [W] [service.go:132] login to server failed: dial tcp 44.237.78.176:7000: i/o timeout\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div><iframe src=\"http://localhost: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"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Keyboard interruption in main thread... closing server.\n",
      "Killing tunnel 0.0.0.0:7860 <> None\n"
     ]
    },
    {
     "data": {
      "text/plain": []
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#INTERFACE WITH ONLY TEXT\n",
    "\n",
    "# Generate options for hours (00-23) \n",
    "hour_options = [f\"{i:02d}:00:00\" for i in range(24)]\n",
    "\n",
    "model_answer= ''\n",
    "general_context= ''\n",
    "# Define the initial state with some initial context.\n",
    "print(general_context)\n",
    "initial_state = {'context': general_context}\n",
    "initial_context= initial_state['context']\n",
    "# Create the Gradio interface.\n",
    "iface = gr.Interface(\n",
    "    fn=FnAnswer,\n",
    "    inputs=[\n",
    "        gr.Textbox(value=initial_context, visible=False),\n",
    "        gr.Textbox(lines=2, placeholder=\"Type your message here...\"),\n",
    "        gr.Radio(choices=['Luxembourg Gare, Luxembourg', 'Kirchberg Campus, Kirchberg', 'Belval Campus, Belval', 'Eiffel Tower, Paris', 'Thionville, France'], label='Choose a location for your car', value= 'Kirchberg Campus, Kirchberg', show_label=True),\n",
    "        gr.Dropdown(choices=hour_options, label=\"What time is it?\", value = \"08:00:00\"),\n",
    "        gr.Radio([\"Yes\", \"No\"], label=\"Delete the conversation history?\", value = 'No'),\n",
    "        gr.State()  # This will keep track of the context state across interactions.\n",
    "    ],\n",
    "    outputs=[\n",
    "        gr.Textbox(),\n",
    "        gr.Textbox(visible=False),\n",
    "        gr.State()\n",
    "    ]\n",
    ")\n",
    "gr.close_all()\n",
    "# Launch the interface.\n",
    "iface.launch(debug=True, share=True, server_name=\"0.0.0.0\", server_port=7860)\n",
    "#contextual=gr.Textbox(value=general_context, visible=False)\n",
    "#demo = gr.Interface(fn=FnAnswer, inputs=[contextual,\"text\"], outputs=[\"text\", contextual])\n",
    "\n",
    "#demo.launch()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "collapsed": true,
    "id": "mZTt3y3_KOOF"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Closing server running on port: 7860\n",
      "Closing server running on port: 7860\n",
      "Closing server running on port: 7860\n",
      "Closing server running on port: 7860\n",
      "Closing server running on port: 7860\n",
      "Closing server running on port: 7860\n",
      "Closing server running on port: 7860\n",
      "Closing server running on port: 7860\n",
      "Closing server running on port: 7860\n",
      "Closing server running on port: 7860\n",
      "Running on local URL:  http://0.0.0.0:7860\n"
     ]
    },
    {
     "ename": "KeyboardInterrupt",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[69], line 42\u001b[0m\n\u001b[1;32m     40\u001b[0m gr\u001b[38;5;241m.\u001b[39mclose_all()\n\u001b[1;32m     41\u001b[0m \u001b[38;5;66;03m# Launch the interface.\u001b[39;00m\n\u001b[0;32m---> 42\u001b[0m \u001b[43miface\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlaunch\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdebug\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mshare\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mserver_name\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m0.0.0.0\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mserver_port\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m7860\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mssl_verify\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/gradio/blocks.py:2068\u001b[0m, in \u001b[0;36mBlocks.launch\u001b[0;34m(self, inline, inbrowser, share, debug, max_threads, auth, auth_message, prevent_thread_lock, show_error, server_name, server_port, height, width, favicon_path, ssl_keyfile, ssl_certfile, ssl_keyfile_password, ssl_verify, quiet, show_api, allowed_paths, blocked_paths, root_path, app_kwargs, state_session_capacity, share_server_address, share_server_protocol, _frontend)\u001b[0m\n\u001b[1;32m   2066\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m   2067\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mshare_url \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m-> 2068\u001b[0m         share_url \u001b[38;5;241m=\u001b[39m \u001b[43mnetworking\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msetup_tunnel\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m   2069\u001b[0m \u001b[43m            \u001b[49m\u001b[43mlocal_host\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mserver_name\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   2070\u001b[0m \u001b[43m            \u001b[49m\u001b[43mlocal_port\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mserver_port\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   2071\u001b[0m \u001b[43m            \u001b[49m\u001b[43mshare_token\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshare_token\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   2072\u001b[0m \u001b[43m            \u001b[49m\u001b[43mshare_server_address\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mshare_server_address\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m   2073\u001b[0m \u001b[43m        \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m   2074\u001b[0m         parsed_url \u001b[38;5;241m=\u001b[39m urlparse(share_url)\n\u001b[1;32m   2075\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mshare_url \u001b[38;5;241m=\u001b[39m urlunparse(\n\u001b[1;32m   2076\u001b[0m             (\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mshare_server_protocol,) \u001b[38;5;241m+\u001b[39m parsed_url[\u001b[38;5;241m1\u001b[39m:]\n\u001b[1;32m   2077\u001b[0m         )\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/gradio/networking.py:229\u001b[0m, in \u001b[0;36msetup_tunnel\u001b[0;34m(local_host, local_port, share_token, share_server_address)\u001b[0m\n\u001b[1;32m    227\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m share_server_address \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m    228\u001b[0m     \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 229\u001b[0m         response \u001b[38;5;241m=\u001b[39m \u001b[43mhttpx\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget\u001b[49m\u001b[43m(\u001b[49m\u001b[43mGRADIO_API_SERVER\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;241;43m30\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m    230\u001b[0m         payload \u001b[38;5;241m=\u001b[39m response\u001b[38;5;241m.\u001b[39mjson()[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m    231\u001b[0m         remote_host, remote_port \u001b[38;5;241m=\u001b[39m payload[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhost\u001b[39m\u001b[38;5;124m\"\u001b[39m], \u001b[38;5;28mint\u001b[39m(payload[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mport\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpx/_api.py:196\u001b[0m, in \u001b[0;36mget\u001b[0;34m(url, params, headers, cookies, auth, proxy, proxies, follow_redirects, cert, verify, timeout, trust_env)\u001b[0m\n\u001b[1;32m    173\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mget\u001b[39m(\n\u001b[1;32m    174\u001b[0m     url: URLTypes,\n\u001b[1;32m    175\u001b[0m     \u001b[38;5;241m*\u001b[39m,\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    186\u001b[0m     trust_env: \u001b[38;5;28mbool\u001b[39m \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m    187\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Response:\n\u001b[1;32m    188\u001b[0m \u001b[38;5;250m    \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m    189\u001b[0m \u001b[38;5;124;03m    Sends a `GET` request.\u001b[39;00m\n\u001b[1;32m    190\u001b[0m \n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    194\u001b[0m \u001b[38;5;124;03m    on this function, as `GET` requests should not include a request body.\u001b[39;00m\n\u001b[1;32m    195\u001b[0m \u001b[38;5;124;03m    \"\"\"\u001b[39;00m\n\u001b[0;32m--> 196\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    197\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mGET\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\n\u001b[1;32m    198\u001b[0m \u001b[43m        \u001b[49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    199\u001b[0m \u001b[43m        \u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    200\u001b[0m \u001b[43m        \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    201\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcookies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcookies\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    202\u001b[0m \u001b[43m        \u001b[49m\u001b[43mauth\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mauth\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    203\u001b[0m \u001b[43m        \u001b[49m\u001b[43mproxy\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproxy\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    204\u001b[0m \u001b[43m        \u001b[49m\u001b[43mproxies\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mproxies\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    205\u001b[0m \u001b[43m        \u001b[49m\u001b[43mfollow_redirects\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfollow_redirects\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    206\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcert\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcert\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    207\u001b[0m \u001b[43m        \u001b[49m\u001b[43mverify\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mverify\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    208\u001b[0m \u001b[43m        \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    209\u001b[0m \u001b[43m        \u001b[49m\u001b[43mtrust_env\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtrust_env\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    210\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpx/_api.py:104\u001b[0m, in \u001b[0;36mrequest\u001b[0;34m(method, url, params, content, data, files, json, headers, cookies, auth, proxy, proxies, timeout, follow_redirects, verify, cert, trust_env)\u001b[0m\n\u001b[1;32m     44\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m     45\u001b[0m \u001b[38;5;124;03mSends an HTTP request.\u001b[39;00m\n\u001b[1;32m     46\u001b[0m \n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m     93\u001b[0m \u001b[38;5;124;03m```\u001b[39;00m\n\u001b[1;32m     94\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m     95\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m Client(\n\u001b[1;32m     96\u001b[0m     cookies\u001b[38;5;241m=\u001b[39mcookies,\n\u001b[1;32m     97\u001b[0m     proxy\u001b[38;5;241m=\u001b[39mproxy,\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    102\u001b[0m     trust_env\u001b[38;5;241m=\u001b[39mtrust_env,\n\u001b[1;32m    103\u001b[0m ) \u001b[38;5;28;01mas\u001b[39;00m client:\n\u001b[0;32m--> 104\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mclient\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrequest\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    105\u001b[0m \u001b[43m        \u001b[49m\u001b[43mmethod\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmethod\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    106\u001b[0m \u001b[43m        \u001b[49m\u001b[43murl\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43murl\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    107\u001b[0m \u001b[43m        \u001b[49m\u001b[43mcontent\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcontent\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    108\u001b[0m \u001b[43m        \u001b[49m\u001b[43mdata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    109\u001b[0m \u001b[43m        \u001b[49m\u001b[43mfiles\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfiles\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    110\u001b[0m \u001b[43m        \u001b[49m\u001b[43mjson\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mjson\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    111\u001b[0m \u001b[43m        \u001b[49m\u001b[43mparams\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mparams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    112\u001b[0m \u001b[43m        \u001b[49m\u001b[43mheaders\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mheaders\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    113\u001b[0m \u001b[43m        \u001b[49m\u001b[43mauth\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mauth\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    114\u001b[0m \u001b[43m        \u001b[49m\u001b[43mfollow_redirects\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfollow_redirects\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    115\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpx/_client.py:828\u001b[0m, in \u001b[0;36mClient.request\u001b[0;34m(self, method, url, content, data, files, json, params, headers, cookies, auth, follow_redirects, timeout, extensions)\u001b[0m\n\u001b[1;32m    813\u001b[0m     warnings\u001b[38;5;241m.\u001b[39mwarn(message, \u001b[38;5;167;01mDeprecationWarning\u001b[39;00m)\n\u001b[1;32m    815\u001b[0m request \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mbuild_request(\n\u001b[1;32m    816\u001b[0m     method\u001b[38;5;241m=\u001b[39mmethod,\n\u001b[1;32m    817\u001b[0m     url\u001b[38;5;241m=\u001b[39murl,\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    826\u001b[0m     extensions\u001b[38;5;241m=\u001b[39mextensions,\n\u001b[1;32m    827\u001b[0m )\n\u001b[0;32m--> 828\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msend\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mauth\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mauth\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mfollow_redirects\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfollow_redirects\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpx/_client.py:915\u001b[0m, in \u001b[0;36mClient.send\u001b[0;34m(self, request, stream, auth, follow_redirects)\u001b[0m\n\u001b[1;32m    907\u001b[0m follow_redirects \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m    908\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mfollow_redirects\n\u001b[1;32m    909\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(follow_redirects, UseClientDefault)\n\u001b[1;32m    910\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m follow_redirects\n\u001b[1;32m    911\u001b[0m )\n\u001b[1;32m    913\u001b[0m auth \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_build_request_auth(request, auth)\n\u001b[0;32m--> 915\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_send_handling_auth\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    916\u001b[0m \u001b[43m    \u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    917\u001b[0m \u001b[43m    \u001b[49m\u001b[43mauth\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mauth\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    918\u001b[0m \u001b[43m    \u001b[49m\u001b[43mfollow_redirects\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfollow_redirects\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    919\u001b[0m \u001b[43m    \u001b[49m\u001b[43mhistory\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m[\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    920\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    921\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m    922\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m stream:\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpx/_client.py:943\u001b[0m, in \u001b[0;36mClient._send_handling_auth\u001b[0;34m(self, request, auth, follow_redirects, history)\u001b[0m\n\u001b[1;32m    940\u001b[0m request \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mnext\u001b[39m(auth_flow)\n\u001b[1;32m    942\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 943\u001b[0m     response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_send_handling_redirects\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    944\u001b[0m \u001b[43m        \u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    945\u001b[0m \u001b[43m        \u001b[49m\u001b[43mfollow_redirects\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mfollow_redirects\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    946\u001b[0m \u001b[43m        \u001b[49m\u001b[43mhistory\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mhistory\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m    947\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    948\u001b[0m     \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m    949\u001b[0m         \u001b[38;5;28;01mtry\u001b[39;00m:\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpx/_client.py:980\u001b[0m, in \u001b[0;36mClient._send_handling_redirects\u001b[0;34m(self, request, follow_redirects, history)\u001b[0m\n\u001b[1;32m    977\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m hook \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_event_hooks[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mrequest\u001b[39m\u001b[38;5;124m\"\u001b[39m]:\n\u001b[1;32m    978\u001b[0m     hook(request)\n\u001b[0;32m--> 980\u001b[0m response \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_send_single_request\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    981\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m    982\u001b[0m     \u001b[38;5;28;01mfor\u001b[39;00m hook \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_event_hooks[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mresponse\u001b[39m\u001b[38;5;124m\"\u001b[39m]:\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpx/_client.py:1016\u001b[0m, in \u001b[0;36mClient._send_single_request\u001b[0;34m(self, request)\u001b[0m\n\u001b[1;32m   1011\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\n\u001b[1;32m   1012\u001b[0m         \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAttempted to send an async request with a sync Client instance.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m   1013\u001b[0m     )\n\u001b[1;32m   1015\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m request_context(request\u001b[38;5;241m=\u001b[39mrequest):\n\u001b[0;32m-> 1016\u001b[0m     response \u001b[38;5;241m=\u001b[39m \u001b[43mtransport\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhandle_request\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m   1018\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(response\u001b[38;5;241m.\u001b[39mstream, SyncByteStream)\n\u001b[1;32m   1020\u001b[0m response\u001b[38;5;241m.\u001b[39mrequest \u001b[38;5;241m=\u001b[39m request\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpx/_transports/default.py:231\u001b[0m, in \u001b[0;36mHTTPTransport.handle_request\u001b[0;34m(self, request)\u001b[0m\n\u001b[1;32m    218\u001b[0m req \u001b[38;5;241m=\u001b[39m httpcore\u001b[38;5;241m.\u001b[39mRequest(\n\u001b[1;32m    219\u001b[0m     method\u001b[38;5;241m=\u001b[39mrequest\u001b[38;5;241m.\u001b[39mmethod,\n\u001b[1;32m    220\u001b[0m     url\u001b[38;5;241m=\u001b[39mhttpcore\u001b[38;5;241m.\u001b[39mURL(\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    228\u001b[0m     extensions\u001b[38;5;241m=\u001b[39mrequest\u001b[38;5;241m.\u001b[39mextensions,\n\u001b[1;32m    229\u001b[0m )\n\u001b[1;32m    230\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m map_httpcore_exceptions():\n\u001b[0;32m--> 231\u001b[0m     resp \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_pool\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhandle_request\u001b[49m\u001b[43m(\u001b[49m\u001b[43mreq\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    233\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(resp\u001b[38;5;241m.\u001b[39mstream, typing\u001b[38;5;241m.\u001b[39mIterable)\n\u001b[1;32m    235\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m Response(\n\u001b[1;32m    236\u001b[0m     status_code\u001b[38;5;241m=\u001b[39mresp\u001b[38;5;241m.\u001b[39mstatus,\n\u001b[1;32m    237\u001b[0m     headers\u001b[38;5;241m=\u001b[39mresp\u001b[38;5;241m.\u001b[39mheaders,\n\u001b[1;32m    238\u001b[0m     stream\u001b[38;5;241m=\u001b[39mResponseStream(resp\u001b[38;5;241m.\u001b[39mstream),\n\u001b[1;32m    239\u001b[0m     extensions\u001b[38;5;241m=\u001b[39mresp\u001b[38;5;241m.\u001b[39mextensions,\n\u001b[1;32m    240\u001b[0m )\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpcore/_sync/connection_pool.py:268\u001b[0m, in \u001b[0;36mConnectionPool.handle_request\u001b[0;34m(self, request)\u001b[0m\n\u001b[1;32m    266\u001b[0m     \u001b[38;5;28;01mwith\u001b[39;00m ShieldCancellation():\n\u001b[1;32m    267\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mresponse_closed(status)\n\u001b[0;32m--> 268\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m exc\n\u001b[1;32m    269\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m    270\u001b[0m     \u001b[38;5;28;01mbreak\u001b[39;00m\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpcore/_sync/connection_pool.py:251\u001b[0m, in \u001b[0;36mConnectionPool.handle_request\u001b[0;34m(self, request)\u001b[0m\n\u001b[1;32m    248\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m exc\n\u001b[1;32m    250\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 251\u001b[0m     response \u001b[38;5;241m=\u001b[39m \u001b[43mconnection\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhandle_request\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    252\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m ConnectionNotAvailable:\n\u001b[1;32m    253\u001b[0m     \u001b[38;5;66;03m# The ConnectionNotAvailable exception is a special case, that\u001b[39;00m\n\u001b[1;32m    254\u001b[0m     \u001b[38;5;66;03m# indicates we need to retry the request on a new connection.\u001b[39;00m\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    258\u001b[0m     \u001b[38;5;66;03m# might end up as an HTTP/2 connection, but which actually ends\u001b[39;00m\n\u001b[1;32m    259\u001b[0m     \u001b[38;5;66;03m# up as HTTP/1.1.\u001b[39;00m\n\u001b[1;32m    260\u001b[0m     \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_pool_lock:\n\u001b[1;32m    261\u001b[0m         \u001b[38;5;66;03m# Maintain our position in the request queue, but reset the\u001b[39;00m\n\u001b[1;32m    262\u001b[0m         \u001b[38;5;66;03m# status so that the request becomes queued again.\u001b[39;00m\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpcore/_sync/connection.py:103\u001b[0m, in \u001b[0;36mHTTPConnection.handle_request\u001b[0;34m(self, request)\u001b[0m\n\u001b[1;32m    100\u001b[0m     \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_connection\u001b[38;5;241m.\u001b[39mis_available():\n\u001b[1;32m    101\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m ConnectionNotAvailable()\n\u001b[0;32m--> 103\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_connection\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhandle_request\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrequest\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpcore/_sync/http11.py:133\u001b[0m, in \u001b[0;36mHTTP11Connection.handle_request\u001b[0;34m(self, request)\u001b[0m\n\u001b[1;32m    131\u001b[0m     \u001b[38;5;28;01mwith\u001b[39;00m Trace(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mresponse_closed\u001b[39m\u001b[38;5;124m\"\u001b[39m, logger, request) \u001b[38;5;28;01mas\u001b[39;00m trace:\n\u001b[1;32m    132\u001b[0m         \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_response_closed()\n\u001b[0;32m--> 133\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m exc\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpcore/_sync/http11.py:111\u001b[0m, in \u001b[0;36mHTTP11Connection.handle_request\u001b[0;34m(self, request)\u001b[0m\n\u001b[1;32m    101\u001b[0m     \u001b[38;5;28;01mpass\u001b[39;00m\n\u001b[1;32m    103\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m Trace(\n\u001b[1;32m    104\u001b[0m     \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mreceive_response_headers\u001b[39m\u001b[38;5;124m\"\u001b[39m, logger, request, kwargs\n\u001b[1;32m    105\u001b[0m ) \u001b[38;5;28;01mas\u001b[39;00m trace:\n\u001b[1;32m    106\u001b[0m     (\n\u001b[1;32m    107\u001b[0m         http_version,\n\u001b[1;32m    108\u001b[0m         status,\n\u001b[1;32m    109\u001b[0m         reason_phrase,\n\u001b[1;32m    110\u001b[0m         headers,\n\u001b[0;32m--> 111\u001b[0m     ) \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_receive_response_headers\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    112\u001b[0m     trace\u001b[38;5;241m.\u001b[39mreturn_value \u001b[38;5;241m=\u001b[39m (\n\u001b[1;32m    113\u001b[0m         http_version,\n\u001b[1;32m    114\u001b[0m         status,\n\u001b[1;32m    115\u001b[0m         reason_phrase,\n\u001b[1;32m    116\u001b[0m         headers,\n\u001b[1;32m    117\u001b[0m     )\n\u001b[1;32m    119\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m Response(\n\u001b[1;32m    120\u001b[0m     status\u001b[38;5;241m=\u001b[39mstatus,\n\u001b[1;32m    121\u001b[0m     headers\u001b[38;5;241m=\u001b[39mheaders,\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    127\u001b[0m     },\n\u001b[1;32m    128\u001b[0m )\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpcore/_sync/http11.py:176\u001b[0m, in \u001b[0;36mHTTP11Connection._receive_response_headers\u001b[0;34m(self, request)\u001b[0m\n\u001b[1;32m    173\u001b[0m timeout \u001b[38;5;241m=\u001b[39m timeouts\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mread\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m)\n\u001b[1;32m    175\u001b[0m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[0;32m--> 176\u001b[0m     event \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_receive_event\u001b[49m\u001b[43m(\u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    177\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(event, h11\u001b[38;5;241m.\u001b[39mResponse):\n\u001b[1;32m    178\u001b[0m         \u001b[38;5;28;01mbreak\u001b[39;00m\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpcore/_sync/http11.py:212\u001b[0m, in \u001b[0;36mHTTP11Connection._receive_event\u001b[0;34m(self, timeout)\u001b[0m\n\u001b[1;32m    209\u001b[0m     event \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_h11_state\u001b[38;5;241m.\u001b[39mnext_event()\n\u001b[1;32m    211\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m event \u001b[38;5;129;01mis\u001b[39;00m h11\u001b[38;5;241m.\u001b[39mNEED_DATA:\n\u001b[0;32m--> 212\u001b[0m     data \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_network_stream\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m    213\u001b[0m \u001b[43m        \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mREAD_NUM_BYTES\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mtimeout\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtimeout\u001b[49m\n\u001b[1;32m    214\u001b[0m \u001b[43m    \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    216\u001b[0m     \u001b[38;5;66;03m# If we feed this case through h11 we'll raise an exception like:\u001b[39;00m\n\u001b[1;32m    217\u001b[0m     \u001b[38;5;66;03m#\u001b[39;00m\n\u001b[1;32m    218\u001b[0m     \u001b[38;5;66;03m#     httpcore.RemoteProtocolError: can't handle event type\u001b[39;00m\n\u001b[0;32m   (...)\u001b[0m\n\u001b[1;32m    222\u001b[0m     \u001b[38;5;66;03m# perspective. Instead we handle this case distinctly and treat\u001b[39;00m\n\u001b[1;32m    223\u001b[0m     \u001b[38;5;66;03m# it as a ConnectError.\u001b[39;00m\n\u001b[1;32m    224\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m data \u001b[38;5;241m==\u001b[39m \u001b[38;5;124mb\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_h11_state\u001b[38;5;241m.\u001b[39mtheir_state \u001b[38;5;241m==\u001b[39m h11\u001b[38;5;241m.\u001b[39mSEND_RESPONSE:\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/httpcore/_backends/sync.py:126\u001b[0m, in \u001b[0;36mSyncStream.read\u001b[0;34m(self, max_bytes, timeout)\u001b[0m\n\u001b[1;32m    124\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m map_exceptions(exc_map):\n\u001b[1;32m    125\u001b[0m     \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sock\u001b[38;5;241m.\u001b[39msettimeout(timeout)\n\u001b[0;32m--> 126\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sock\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrecv\u001b[49m\u001b[43m(\u001b[49m\u001b[43mmax_bytes\u001b[49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m/usr/lib/python3.10/ssl.py:1259\u001b[0m, in \u001b[0;36mSSLSocket.recv\u001b[0;34m(self, buflen, flags)\u001b[0m\n\u001b[1;32m   1255\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m flags \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m   1256\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m   1257\u001b[0m             \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnon-zero flags not allowed in calls to recv() on \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m\n\u001b[1;32m   1258\u001b[0m             \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m)\n\u001b[0;32m-> 1259\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[43mbuflen\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m   1260\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m   1261\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39mrecv(buflen, flags)\n",
      "File \u001b[0;32m/usr/lib/python3.10/ssl.py:1132\u001b[0m, in \u001b[0;36mSSLSocket.read\u001b[0;34m(self, len, buffer)\u001b[0m\n\u001b[1;32m   1130\u001b[0m         \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_sslobj\u001b[38;5;241m.\u001b[39mread(\u001b[38;5;28mlen\u001b[39m, buffer)\n\u001b[1;32m   1131\u001b[0m     \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1132\u001b[0m         \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_sslobj\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mread\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mlen\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m   1133\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m SSLError \u001b[38;5;28;01mas\u001b[39;00m x:\n\u001b[1;32m   1134\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m x\u001b[38;5;241m.\u001b[39margs[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m==\u001b[39m SSL_ERROR_EOF \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msuppress_ragged_eofs:\n",
      "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
     ]
    }
   ],
   "source": [
    "#INTERFACE WITH AUDIO TO AUDIO\n",
    "\n",
    "#to be able to use the microphone on chrome, you will have to go to chrome://flags/#unsafely-treat-insecure-origin-as-secure and enter http://10.186.115.21:7860/ \n",
    "#in \"Insecure origins treated as secure\", enable it and relaunch chrome\n",
    "\n",
    "#example question: \n",
    "# what's the weather like outside?\n",
    "# What's the closest restaurant from here?\n",
    "\n",
    "\n",
    "\n",
    "# Generate options for hours (00-23) \n",
    "hour_options = [f\"{i:02d}:00:00\" for i in range(24)]\n",
    "\n",
    "model_answer= ''\n",
    "general_context= ''\n",
    "# Define the initial state with some initial context.\n",
    "print(general_context)\n",
    "initial_state = {'context': general_context}\n",
    "initial_context= initial_state['context']\n",
    "# Create the Gradio interface.\n",
    "iface = gr.Interface(\n",
    "    fn=transcript,\n",
    "    inputs=[\n",
    "        gr.Textbox(value=initial_context, visible=False),\n",
    "        gr.Audio( type='filepath', label = 'input audio'),\n",
    "        gr.Radio(choices=['Donald Trump', 'Eddie Murphy'], label='Choose a voice', value= 'Donald Trump', show_label=True),  # Radio button for voice selection\n",
    "        gr.Radio(choices=['Luxembourg Gare, Luxembourg', 'Kirchberg Campus, Kirchberg', 'Belval Campus, Belval', 'Eiffel Tower, Paris', 'Thionville, France'], label='Choose a location for your car', value= 'Kirchberg Campus, Kirchberg', show_label=True),\n",
    "        gr.Dropdown(choices=hour_options, label=\"What time is it?\", value = \"08:00:00\"),\n",
    "        gr.Radio([\"Yes\", \"No\"], label=\"Delete the conversation history?\", value = 'No'),\n",
    "        gr.State()  # This will keep track of the context state across interactions.\n",
    "    ],\n",
    "    outputs=[\n",
    "        gr.Audio(label = 'output audio'),\n",
    "        gr.Textbox(visible=False),\n",
    "        gr.State()\n",
    "    ]\n",
    ")\n",
    "#close all interfaces open to make the port available\n",
    "gr.close_all()\n",
    "# Launch the interface.\n",
    "iface.launch(debug=True, share=True, server_name=\"0.0.0.0\", server_port=7860, ssl_verify=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Other possible APIs to use"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "ename": "JSONDecodeError",
     "evalue": "Expecting value: line 1 column 1 (char 0)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mJSONDecodeError\u001b[0m                           Traceback (most recent call last)",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/requests/models.py:971\u001b[0m, in \u001b[0;36mResponse.json\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m    970\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 971\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mcomplexjson\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mloads\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtext\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    972\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m JSONDecodeError \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m    973\u001b[0m     \u001b[38;5;66;03m# Catch JSON-related errors and raise as requests.JSONDecodeError\u001b[39;00m\n\u001b[1;32m    974\u001b[0m     \u001b[38;5;66;03m# This aliases json.JSONDecodeError and simplejson.JSONDecodeError\u001b[39;00m\n",
      "File \u001b[0;32m/usr/lib/python3.10/json/__init__.py:346\u001b[0m, in \u001b[0;36mloads\u001b[0;34m(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)\u001b[0m\n\u001b[1;32m    343\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m    344\u001b[0m         parse_int \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m parse_float \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m\n\u001b[1;32m    345\u001b[0m         parse_constant \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m object_pairs_hook \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m kw):\n\u001b[0;32m--> 346\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_default_decoder\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdecode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    347\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mcls\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n",
      "File \u001b[0;32m/usr/lib/python3.10/json/decoder.py:337\u001b[0m, in \u001b[0;36mJSONDecoder.decode\u001b[0;34m(self, s, _w)\u001b[0m\n\u001b[1;32m    333\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"Return the Python representation of ``s`` (a ``str`` instance\u001b[39;00m\n\u001b[1;32m    334\u001b[0m \u001b[38;5;124;03mcontaining a JSON document).\u001b[39;00m\n\u001b[1;32m    335\u001b[0m \n\u001b[1;32m    336\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m--> 337\u001b[0m obj, end \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mraw_decode\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43midx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m_w\u001b[49m\u001b[43m(\u001b[49m\u001b[43ms\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mend\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    338\u001b[0m end \u001b[38;5;241m=\u001b[39m _w(s, end)\u001b[38;5;241m.\u001b[39mend()\n",
      "File \u001b[0;32m/usr/lib/python3.10/json/decoder.py:355\u001b[0m, in \u001b[0;36mJSONDecoder.raw_decode\u001b[0;34m(self, s, idx)\u001b[0m\n\u001b[1;32m    354\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mStopIteration\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[0;32m--> 355\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m JSONDecodeError(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mExpecting value\u001b[39m\u001b[38;5;124m\"\u001b[39m, s, err\u001b[38;5;241m.\u001b[39mvalue) \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m    356\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m obj, end\n",
      "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting value: line 1 column 1 (char 0)",
      "\nDuring handling of the above exception, another exception occurred:\n",
      "\u001b[0;31mJSONDecodeError\u001b[0m                           Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[80], line 25\u001b[0m\n\u001b[1;32m     20\u001b[0m             \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[1;32m     22\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m. \u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mjoin(results)\n\u001b[0;32m---> 25\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[43msearch_nearby\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m49.625892805337514\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m6.160417066963513\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43myour location\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mTOMTOM_KEY\u001b[49m\u001b[43m)\u001b[49m)\n",
      "Cell \u001b[0;32mIn[80], line 17\u001b[0m, in \u001b[0;36msearch_nearby\u001b[0;34m(lat, lon, city, key)\u001b[0m\n\u001b[1;32m      9\u001b[0m results \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m     11\u001b[0m r \u001b[38;5;241m=\u001b[39m requests\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mhttps://api.tomtom.com/search/2/nearbySearch/.json?key=\u001b[39m\u001b[38;5;132;01m{0}\u001b[39;00m\u001b[38;5;124m&lat=\u001b[39m\u001b[38;5;132;01m{1}\u001b[39;00m\u001b[38;5;124m&lon=\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m&radius=10000&limit=50\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;241m.\u001b[39mformat(\n\u001b[1;32m     12\u001b[0m                     key,\n\u001b[1;32m     13\u001b[0m                     lat,\n\u001b[1;32m     14\u001b[0m                     lon\n\u001b[1;32m     15\u001b[0m ))\n\u001b[0;32m---> 17\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m result \u001b[38;5;129;01min\u001b[39;00m \u001b[43mr\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mjson\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mresults\u001b[39m\u001b[38;5;124m'\u001b[39m]:\n\u001b[1;32m     18\u001b[0m     results\u001b[38;5;241m.\u001b[39mappend(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mThe \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;241m.\u001b[39mjoin(result[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mpoi\u001b[39m\u001b[38;5;124m'\u001b[39m][\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcategories\u001b[39m\u001b[38;5;124m'\u001b[39m])\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mresult[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mpoi\u001b[39m\u001b[38;5;124m'\u001b[39m][\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m is \u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mint\u001b[39m(result[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mdist\u001b[39m\u001b[38;5;124m'\u001b[39m])\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m meters far from \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcity\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m     19\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(results) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m7\u001b[39m:\n",
      "File \u001b[0;32m/usr/local/lib/python3.10/dist-packages/requests/models.py:975\u001b[0m, in \u001b[0;36mResponse.json\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m    971\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m complexjson\u001b[38;5;241m.\u001b[39mloads(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtext, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n\u001b[1;32m    972\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m JSONDecodeError \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m    973\u001b[0m     \u001b[38;5;66;03m# Catch JSON-related errors and raise as requests.JSONDecodeError\u001b[39;00m\n\u001b[1;32m    974\u001b[0m     \u001b[38;5;66;03m# This aliases json.JSONDecodeError and simplejson.JSONDecodeError\u001b[39;00m\n\u001b[0;32m--> 975\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m RequestsJSONDecodeError(e\u001b[38;5;241m.\u001b[39mmsg, e\u001b[38;5;241m.\u001b[39mdoc, e\u001b[38;5;241m.\u001b[39mpos)\n",
      "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting value: line 1 column 1 (char 0)"
     ]
    }
   ],
   "source": [
    "\n",
    "def search_nearby(lat, lon, city, key):\n",
    "    \"\"\"\n",
    "    :param lat: latitude\n",
    "    :param lon: longitude\n",
    "    :param key: api key\n",
    "    :param type: type of poi\n",
    "    :return: [5] results ['poi']['name']/['freeformAddress'] || ['position']['lat']/['lon']\n",
    "    \"\"\"\n",
    "    results = []\n",
    "\n",
    "    r = requests.get('https://api.tomtom.com/search/2/nearbySearch/.json?key={0}&lat={1}&lon={2}&radius=10000&limit=50'.format(\n",
    "                        key,\n",
    "                        lat,\n",
    "                        lon\n",
    "    ))\n",
    "\n",
    "    for result in r.json()['results']:\n",
    "        results.append(f\"The {' '.join(result['poi']['categories'])} {result['poi']['name']} is {int(result['dist'])} meters far from {city}\")\n",
    "        if len(results) == 7:\n",
    "            break\n",
    "\n",
    "    return \". \".join(results)\n",
    "\n",
    "\n",
    "print(search_nearby('49.625892805337514', '6.160417066963513', 'your location', TOMTOM_KEY))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "accelerator": "GPU",
  "colab": {
   "gpuType": "T4",
   "provenance": []
  },
  "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.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}