sasan commited on
Commit
a6f6ce8
·
unverified ·
2 Parent(s): 65dafa6 9185640

Merge pull request #2 from sasan-j/feature/remove-nexus

Browse files
Files changed (8) hide show
  1. apis.py +0 -54
  2. kitt/core/stt.py +39 -0
  3. llama2.py +0 -86
  4. main.py +9 -195
  5. stt.ipynb +0 -292
  6. stttotts.py +0 -177
  7. test_raven.ipynb +0 -936
  8. tts.ipynb +0 -0
apis.py DELETED
@@ -1,54 +0,0 @@
1
- from geopy.geocoders import Nominatim
2
-
3
-
4
- ###################################################
5
- # Functions we want to articulate (APIs calls): ###
6
- ###################################################
7
-
8
- ########################################################################################
9
- # Functions called in the articulated functions (not directly called by the model): ###
10
- ########################################################################################
11
-
12
- geolocator = Nominatim(user_agent="MyApp")
13
-
14
- def find_precise_place(lat, lon):
15
- location = geolocator.reverse(str(lat) +", " + str(lon))
16
- return location.raw.get('display_name', {})
17
-
18
- def find_coordinates(address):
19
- coord = geolocator.geocode(address)
20
- lat = coord.latitude
21
- lon = coord.longitude
22
- return(lat,lon)
23
-
24
-
25
- def check_city_coordinates(lat = "", lon = "", city = "", **kwargs):
26
- """
27
- :param lat: latitude
28
- :param lon: longitude
29
- :param city: name of the city
30
-
31
- Checks if the coordinates correspond to the city, if not update the coordinate to correspond to the city
32
- """
33
- if lat != "0" and lon != "0":
34
- reverse = partial(geolocator.reverse, language="en")
35
- location = reverse(f"{lat}, {lon}")
36
- address = location.raw.get('address', {})
37
- city = address.get('city') or address.get('town') or address.get('village') or address.get('county')
38
- else :
39
- reverse = partial(geolocator.reverse, language="en")
40
- location = reverse(f"{lat}, {lon}")
41
- address = location.raw.get('address', {})
42
- city_name = address.get('city') or address.get('town') or address.get('village') or address.get('county')
43
- if city_name is None :
44
- city_name = 'not_found'
45
- print(city_name)
46
- if city_name.lower() != city.lower():
47
- coord = geolocator.geocode(city )
48
- if coord is None:
49
- coord = geolocator.geocode(city)
50
- lat = coord.latitude
51
- lon = coord.longitude
52
- return lat, lon, city
53
-
54
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
kitt/core/stt.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import copy
2
+ import time
3
+
4
+ import gradio as gr
5
+ import numpy as np
6
+ import torch
7
+ import torchaudio
8
+ from loguru import logger
9
+ from transformers import pipeline
10
+
11
+ device = "cuda" if torch.cuda.is_available() else "cpu"
12
+ transcriber = pipeline(
13
+ "automatic-speech-recognition", model="openai/whisper-base.en", device=device
14
+ )
15
+
16
+
17
+ def save_audio_as_wav(data, sample_rate, file_path):
18
+ # make a tensor from the numpy array
19
+ data = torch.tensor(data).reshape(1, -1)
20
+ torchaudio.save(
21
+ file_path, data, sample_rate=sample_rate, bits_per_sample=16, encoding="PCM_S"
22
+ )
23
+
24
+
25
+ def save_and_transcribe_audio(audio):
26
+ sample_rate, data = audio
27
+ try:
28
+ # add timestamp to file name
29
+ filename = f"recordings/audio{time.time()}.wav"
30
+ save_audio_as_wav(data, sample_rate, filename)
31
+ data = data.astype(np.float32)
32
+ data /= np.max(np.abs(data))
33
+ text = transcriber({"sampling_rate": sample_rate, "raw": data})["text"]
34
+ gr.Info(f"Transcribed text is: {text}\nProcessing the input...")
35
+
36
+ except Exception as e:
37
+ logger.error(f"Error: {e}")
38
+ raise Exception("Error transcribing audio.")
39
+ return text
llama2.py DELETED
@@ -1,86 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """llama2
3
-
4
- Automatically generated by Colaboratory.
5
-
6
- Original file is located at
7
- https://colab.research.google.com/drive/15UK6iHd1y0pMMQc-DbZIYhSteoTCUsMH
8
- """
9
-
10
- #install and then restart execution
11
- !pip install accelerate
12
- !pip install bitsandbytes
13
- !pip install optimum
14
- !pip install auto-gptq
15
-
16
- !pip install transformers
17
- from transformers import AutoModelForCausalLM,AutoTokenizer
18
- import torch
19
- !pip install transformers huggingface_hub
20
- from huggingface_hub import notebook_login
21
-
22
- notebook_login()
23
-
24
- mn = 'stabilityai/StableBeluga-7B'
25
- #mn = "TheBloke/Llama-2-7b-Chat-GPTQ"
26
-
27
- model = AutoModelForCausalLM.from_pretrained(mn, device_map=0, load_in_8bit=True)
28
-
29
- #model = AutoModelForCausalLM.from_pretrained(mn, device_map=0, torch_dtype=torch.float16)
30
-
31
- sb_sys = "### System:\nYou are a AI driving assistant in my car, that follows instructions extremely well. Help as much as you can.\n\n"
32
-
33
- def gen(p, maxlen=15, sample=True):
34
- toks = tokr(p, return_tensors="pt")
35
- res = model.generate(**toks.to("cuda"), max_new_tokens=maxlen, do_sample=sample).to('cpu')
36
- return tokr.batch_decode(res)
37
-
38
- tokr = AutoTokenizer.from_pretrained(mn)
39
-
40
- #to have a prompt corresponding to the specific format required by the fine-tuned model Stable Beluga
41
- def mk_prompt(user, syst=sb_sys): return f"{syst}### User: {user}\n\n### Assistant:\n"
42
-
43
- complete_answer= ''
44
-
45
- #attempt to get user location
46
-
47
- import requests
48
-
49
- response = requests.get("http://ip-api.com/json/")
50
- data = response.json()
51
- print(data['city'], data['lat'], data['lon'])
52
- city= data['city']
53
- lat = data['lat']
54
- lon = data['lon']
55
-
56
- import re
57
- model_answer= ''
58
- general_context= f'I am in my car in {city}, latitude {lat}, longitude {lon}, I can move with my car to reach a destination'
59
- pattern = r"Assistant:\\n(.*?)</s>"
60
-
61
- ques = "I hate pizzas"
62
-
63
- ques_ctx = f"""Answer the question with the help of the provided context.
64
-
65
- ## Context
66
-
67
- {general_context} .
68
-
69
- ## Question
70
-
71
- {ques}"""
72
-
73
- complete_answer = str(gen(mk_prompt(ques_ctx), 150))
74
-
75
- match = re.search(pattern, complete_answer, re.DOTALL)
76
-
77
- if match:
78
- # Extracting the text
79
- model_answer = match.group(1)
80
- else:
81
- model_answer = "There has been an error with the generated response."
82
-
83
- general_context += model_answer
84
- print(model_answer)
85
-
86
- print(complete_answer)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
main.py CHANGED
@@ -1,24 +1,14 @@
1
- import time
2
-
3
  import gradio as gr
4
- import numpy as np
5
- import ollama
6
- import torch
7
- import torchaudio
8
- import typer
9
  from langchain.memory import ChatMessageHistory
10
  from langchain.tools import tool
11
- from langchain.tools.base import StructuredTool
12
  from langchain_core.utils.function_calling import convert_to_openai_tool
13
  from loguru import logger
14
- from transformers import pipeline
15
 
16
  from kitt.core import tts_gradio
17
  from kitt.core import utils as kitt_utils
18
  from kitt.core import voice_options
19
-
20
- # from kitt.core.model import process_query
21
  from kitt.core.model import generate_function_call as process_query
 
22
  from kitt.core.tts import prep_for_tts, run_melo_tts, run_tts_fast, run_tts_replicate
23
  from kitt.skills import (
24
  code_interpreter,
@@ -34,7 +24,6 @@ from kitt.skills import (
34
  set_vehicle_destination,
35
  set_vehicle_speed,
36
  )
37
- from kitt.skills import vehicle_status as vehicle_status_fn
38
  from kitt.skills.common import config, vehicle
39
  from kitt.skills.routing import calculate_route, find_address
40
 
@@ -65,54 +54,6 @@ global_context = {
65
  speaker_embedding_cache = {}
66
  history = ChatMessageHistory()
67
 
68
- MODEL_FUNC = "nexusraven"
69
- MODEL_GENERAL = "llama3:instruct"
70
-
71
- RAVEN_PROMPT_FUNC = """You are a helpful AI assistant in a car (vehicle), that follows instructions extremely well. \
72
- Answer questions concisely and do not mention what you base your reply on."
73
-
74
- {raven_tools}
75
-
76
- {history}
77
-
78
- User Query: Question: {input}<human_end>
79
- """
80
-
81
-
82
- HERMES_PROMPT_FUNC = """
83
- <|im_start|>system
84
- You are a helpful AI assistant in a car (vehicle), that follows instructions extremely well. \
85
- Answer questions concisely and do not mention what you base your reply on.<|im_end|>
86
- <|im_start|>user
87
- {{ .Prompt }}<|im_end|>
88
- <|im_start|>assistant
89
- """
90
-
91
-
92
- def get_prompt(template, input, history, tools):
93
- # "vehicle_status": vehicle_status_fn()[0]
94
- kwargs = {"history": history, "input": input}
95
- prompt = "<human>:\n"
96
- for tool in tools:
97
- func_signature, func_docstring = tool.description.split(" - ", 1)
98
- prompt += f'Function:\n<func_start>def {func_signature}<func_end>\n<docstring_start>\n"""\n{func_docstring}\n"""\n<docstring_end>\n'
99
- kwargs["raven_tools"] = prompt
100
-
101
- if history:
102
- kwargs["history"] = f"Previous conversation history:{history}\n"
103
-
104
- return template.format(**kwargs).replace("{{", "{").replace("}}", "}")
105
-
106
-
107
- def use_tool(func_name, kwargs, tools):
108
- for tool in tools:
109
- if tool.name == func_name:
110
- return tool.invoke(input=kwargs)
111
- return None
112
-
113
-
114
- # llm = Ollama(model="nexusraven", stop=["\nReflection:", "\nThought:"], keep_alive=60*10)
115
-
116
 
117
  # Generate options for hours (00-23)
118
  hour_options = [f"{i:02d}:00:00" for i in range(24)]
@@ -136,20 +77,6 @@ def set_time(time_picker):
136
  return vehicle
137
 
138
 
139
- tools = [
140
- # StructuredTool.from_function(get_weather),
141
- # StructuredTool.from_function(find_route),
142
- # StructuredTool.from_function(vehicle_status_fn),
143
- # StructuredTool.from_function(set_vehicle_speed),
144
- # StructuredTool.from_function(set_vehicle_destination),
145
- # StructuredTool.from_function(search_points_of_interest),
146
- # StructuredTool.from_function(search_along_route),
147
- # StructuredTool.from_function(date_time_info),
148
- # StructuredTool.from_function(get_weather_current_location),
149
- # StructuredTool.from_function(code_interpreter),
150
- # StructuredTool.from_function(do_anything_else),
151
- ]
152
-
153
  functions = [
154
  # set_vehicle_speed,
155
  set_vehicle_destination,
@@ -161,59 +88,11 @@ functions = [
161
  openai_tools = [convert_to_openai_tool(tool) for tool in functions]
162
 
163
 
164
- def run_generic_model(query):
165
- print(f"Running the generic model with query: {query}")
166
- data = {
167
- "prompt": f"Answer the question below in a short and concise manner.\n{query}",
168
- "model": MODEL_GENERAL,
169
- "options": {
170
- # "temperature": 0.1,
171
- # "stop":["\nReflection:", "\nThought:"]
172
- },
173
- }
174
- out = ollama.generate(**data)
175
- return out["response"]
176
-
177
-
178
  def clear_history():
179
  logger.info("Clearing the conversation history...")
180
  history.clear()
181
 
182
 
183
- def run_nexusraven_model(query, voice_character, state):
184
- global_context["prompt"] = get_prompt(RAVEN_PROMPT_FUNC, query, "", tools)
185
- print("Prompt: ", global_context["prompt"])
186
- data = {
187
- "prompt": global_context["prompt"],
188
- # "streaming": False,
189
- "model": "nexusraven",
190
- # "model": "smangrul/llama-3-8b-instruct-function-calling",
191
- "raw": True,
192
- "options": {"temperature": 0.5, "stop": ["\nReflection:", "\nThought:"]},
193
- }
194
- out = ollama.generate(**data)
195
- llm_response = out["response"]
196
- if "Call: " in llm_response:
197
- print(f"llm_response: {llm_response}")
198
- llm_response = llm_response.replace("<bot_end>", " ")
199
- func_name, kwargs = extract_func_args(llm_response)
200
- print(f"Function: {func_name}, Args: {kwargs}")
201
- if func_name == "do_anything_else":
202
- output_text = run_generic_model(query)
203
- else:
204
- output_text = use_tool(func_name, kwargs, tools)
205
- else:
206
- output_text = out["response"]
207
-
208
- if type(output_text) == tuple:
209
- output_text = output_text[0]
210
- gr.Info(f"Output text: {output_text}\nGenerating voice output...")
211
- return (
212
- output_text,
213
- tts_gradio(output_text, voice_character, speaker_embedding_cache)[0],
214
- )
215
-
216
-
217
  def run_llama3_model(query, voice_character, state):
218
 
219
  assert len(functions) > 0, "No functions to call"
@@ -249,18 +128,13 @@ def run_llama3_model(query, voice_character, state):
249
 
250
 
251
  def run_model(query, voice_character, state):
252
- model = state.get("model", "nexusraven")
253
  query = query.strip().replace("'", "")
254
  logger.info(
255
  f"Running model: {model} with query: {query}, voice_character: {voice_character} and llm_backend: {state['llm_backend']}, tts_enabled: {state['tts_enabled']}"
256
  )
257
  global_context["query"] = query
258
- if model == "nexusraven":
259
- text, voice = run_nexusraven_model(query, voice_character, state)
260
- elif model == "llama3":
261
- text, voice = run_llama3_model(query, voice_character, state)
262
- else:
263
- text, voice = "Error running model", None
264
 
265
  if not state["enable_history"]:
266
  history.clear()
@@ -308,44 +182,6 @@ def update_vehicle_status(trip_progress, origin, destination, state):
308
  return vehicle, plot, state
309
 
310
 
311
- device = "cuda" if torch.cuda.is_available() else "cpu"
312
- transcriber = pipeline(
313
- "automatic-speech-recognition", model="openai/whisper-base.en", device=device
314
- )
315
-
316
-
317
- def save_audio_as_wav(data, sample_rate, file_path):
318
- # make a tensor from the numpy array
319
- data = torch.tensor(data).reshape(1, -1)
320
- torchaudio.save(
321
- file_path, data, sample_rate=sample_rate, bits_per_sample=16, encoding="PCM_S"
322
- )
323
-
324
-
325
- def save_and_transcribe_audio(audio):
326
- try:
327
- # capture the audio and save it to a file as wav or mp3
328
- # file_name = save("audioinput.wav")
329
- sr, y = audio
330
- # y = y.astype(np.float32)
331
- # y /= np.max(np.abs(y))
332
-
333
- # add timestamp to file name
334
- filename = f"recordings/audio{time.time()}.wav"
335
- save_audio_as_wav(y, sr, filename)
336
-
337
- sr, y = audio
338
- y = y.astype(np.float32)
339
- y /= np.max(np.abs(y))
340
- text = transcriber({"sampling_rate": sr, "raw": y})["text"]
341
- gr.Info(f"Transcribed text is: {text}\nProcessing the input...")
342
-
343
- except Exception as e:
344
- logger.error(f"Error: {e}")
345
- raise Exception("Error transcribing audio.")
346
- return text
347
-
348
-
349
  def save_and_transcribe_run_model(audio, voice_character, state):
350
  text = save_and_transcribe_audio(audio)
351
  out_text, out_voice, vehicle_status, state, update_proxy = run_model(
@@ -494,7 +330,12 @@ def create_demo(tts_server: bool = False, model="llama3"):
494
  0, 100, step=5, label="Trip progress", interactive=True
495
  )
496
 
497
- # map_if = gr.Interface(fn=plot_map, inputs=year_input, outputs=map_plot)
 
 
 
 
 
498
 
499
  with gr.Row():
500
  with gr.Column():
@@ -647,30 +488,3 @@ demo.launch(
647
  ssl_verify=False,
648
  share=False,
649
  )
650
-
651
- app = typer.Typer()
652
-
653
-
654
- @app.command()
655
- def run(tts_server: bool = False):
656
- global demo
657
- demo = create_demo(tts_server)
658
- demo.launch(
659
- debug=True, server_name="0.0.0.0", server_port=7860, ssl_verify=True, share=True
660
- )
661
-
662
-
663
- @app.command()
664
- def dev(tts_server: bool = False, model: str = "llama3"):
665
- demo = create_demo(tts_server, model)
666
- demo.launch(
667
- debug=True,
668
- server_name="0.0.0.0",
669
- server_port=7860,
670
- ssl_verify=False,
671
- share=False,
672
- )
673
-
674
-
675
- if __name__ == "__main__":
676
- app()
 
 
 
1
  import gradio as gr
 
 
 
 
 
2
  from langchain.memory import ChatMessageHistory
3
  from langchain.tools import tool
 
4
  from langchain_core.utils.function_calling import convert_to_openai_tool
5
  from loguru import logger
 
6
 
7
  from kitt.core import tts_gradio
8
  from kitt.core import utils as kitt_utils
9
  from kitt.core import voice_options
 
 
10
  from kitt.core.model import generate_function_call as process_query
11
+ from kitt.core.stt import save_and_transcribe_audio
12
  from kitt.core.tts import prep_for_tts, run_melo_tts, run_tts_fast, run_tts_replicate
13
  from kitt.skills import (
14
  code_interpreter,
 
24
  set_vehicle_destination,
25
  set_vehicle_speed,
26
  )
 
27
  from kitt.skills.common import config, vehicle
28
  from kitt.skills.routing import calculate_route, find_address
29
 
 
54
  speaker_embedding_cache = {}
55
  history = ChatMessageHistory()
56
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  # Generate options for hours (00-23)
59
  hour_options = [f"{i:02d}:00:00" for i in range(24)]
 
77
  return vehicle
78
 
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  functions = [
81
  # set_vehicle_speed,
82
  set_vehicle_destination,
 
88
  openai_tools = [convert_to_openai_tool(tool) for tool in functions]
89
 
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  def clear_history():
92
  logger.info("Clearing the conversation history...")
93
  history.clear()
94
 
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  def run_llama3_model(query, voice_character, state):
97
 
98
  assert len(functions) > 0, "No functions to call"
 
128
 
129
 
130
  def run_model(query, voice_character, state):
131
+ model = state.get("model", "llama3")
132
  query = query.strip().replace("'", "")
133
  logger.info(
134
  f"Running model: {model} with query: {query}, voice_character: {voice_character} and llm_backend: {state['llm_backend']}, tts_enabled: {state['tts_enabled']}"
135
  )
136
  global_context["query"] = query
137
+ text, voice = run_llama3_model(query, voice_character, state)
 
 
 
 
 
138
 
139
  if not state["enable_history"]:
140
  history.clear()
 
182
  return vehicle, plot, state
183
 
184
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  def save_and_transcribe_run_model(audio, voice_character, state):
186
  text = save_and_transcribe_audio(audio)
187
  out_text, out_voice, vehicle_status, state, update_proxy = run_model(
 
330
  0, 100, step=5, label="Trip progress", interactive=True
331
  )
332
 
333
+ # with gr.Column(scale=1, min_width=300):
334
+ # gr.Image("linkedin-1.png", label="Linkedin - Sasan Jafarnejad")
335
+ # gr.Image(
336
+ # "team-ubix.png",
337
+ # label="Research Team - UBIX - University of Luxembourg",
338
+ # )
339
 
340
  with gr.Row():
341
  with gr.Column():
 
488
  ssl_verify=False,
489
  share=False,
490
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stt.ipynb DELETED
@@ -1,292 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "code",
5
- "execution_count": 25,
6
- "metadata": {},
7
- "outputs": [
8
- {
9
- "name": "stderr",
10
- "output_type": "stream",
11
- "text": [
12
- "/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",
13
- " _torch_pytree._register_pytree_node(\n",
14
- "/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",
15
- " _torch_pytree._register_pytree_node(\n",
16
- "/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",
17
- " _torch_pytree._register_pytree_node(\n"
18
- ]
19
- }
20
- ],
21
- "source": [
22
- "#STT (speech to text)\n",
23
- "from transformers import WhisperProcessor, WhisperForConditionalGeneration\n",
24
- "from transformers import pipeline\n",
25
- "import librosa"
26
- ]
27
- },
28
- {
29
- "cell_type": "code",
30
- "execution_count": 3,
31
- "metadata": {},
32
- "outputs": [
33
- {
34
- "name": "stderr",
35
- "output_type": "stream",
36
- "text": [
37
- "Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.\n"
38
- ]
39
- }
40
- ],
41
- "source": [
42
- "# load model and processor for speech-to-text\n",
43
- "processor = WhisperProcessor.from_pretrained(\"openai/whisper-small\")\n",
44
- "modelw = WhisperForConditionalGeneration.from_pretrained(\"openai/whisper-small\")\n",
45
- "# modelw.config.forced_decoder_ids = None"
46
- ]
47
- },
48
- {
49
- "cell_type": "code",
50
- "execution_count": 51,
51
- "metadata": {},
52
- "outputs": [],
53
- "source": [
54
- "device = \"cuda\" if torch.cuda.is_available() else \"cpu\""
55
- ]
56
- },
57
- {
58
- "cell_type": "code",
59
- "execution_count": 52,
60
- "metadata": {},
61
- "outputs": [
62
- {
63
- "name": "stderr",
64
- "output_type": "stream",
65
- "text": [
66
- "Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.\n"
67
- ]
68
- }
69
- ],
70
- "source": [
71
- "transcriber = pipeline(\"automatic-speech-recognition\", model=\"openai/whisper-base.en\", device=device)"
72
- ]
73
- },
74
- {
75
- "cell_type": "code",
76
- "execution_count": 53,
77
- "metadata": {},
78
- "outputs": [
79
- {
80
- "data": {
81
- "text/plain": [
82
- "device(type='cpu')"
83
- ]
84
- },
85
- "execution_count": 53,
86
- "metadata": {},
87
- "output_type": "execute_result"
88
- }
89
- ],
90
- "source": [
91
- "transcriber.device"
92
- ]
93
- },
94
- {
95
- "cell_type": "code",
96
- "execution_count": 58,
97
- "metadata": {},
98
- "outputs": [],
99
- "source": [
100
- "audio = \"/Users/sasan.jafarnejad/dev/uni/talking-car/audio1713724521.779008.wav\"\n",
101
- "audio = \"/Users/sasan.jafarnejad/dev/uni/talking-car/audio/attenborough/neutral.wav\"\n",
102
- "if type(audio) == str:\n",
103
- " link_to_audio = audio\n",
104
- " audio = torchaudio.load(link_to_audio)\n",
105
- " audio = audio[0].squeeze().numpy(), sr\n",
106
- " if len(audio[0].shape) == 2:\n",
107
- " audio = audio[0].mean(axis=0), audio[1]"
108
- ]
109
- },
110
- {
111
- "cell_type": "code",
112
- "execution_count": 59,
113
- "metadata": {},
114
- "outputs": [],
115
- "source": [
116
- "y, sr = audio"
117
- ]
118
- },
119
- {
120
- "cell_type": "code",
121
- "execution_count": 60,
122
- "metadata": {},
123
- "outputs": [],
124
- "source": [
125
- "out = transcriber({\"sampling_rate\": sr, \"raw\":y})[\"text\"]"
126
- ]
127
- },
128
- {
129
- "cell_type": "code",
130
- "execution_count": 61,
131
- "metadata": {},
132
- "outputs": [
133
- {
134
- "data": {
135
- "text/plain": [
136
- "\" If you speed up time, plants begin to reveal their true nature. They're not passive organisms, as you might think, but competitive creatures every bit as aggressive as animals. They're locked in a desperate battle for light and space. They stretch and pulse as they strive to barge their way into pole position. Creepers and vines reach around for the branch or stem of another plant on which to hitch a ride. This is an assassin bug. To us, it's easy enough to spot because it moves. To its prey, that's irrelevant, because it smells like one of their number. The assassin sucks its victims dry and blues their empty husks onto its back. This one is already carrying at least 20 corpses. Its irregular shape makes it hard for other predators to spot it and makes it virtually invisible to its prey, ants. It enters this ant colony unchallenged. Its coat of ant corpses masks its own odour. To the ants, it smells like one of their own, and that's what matters. They'll even run straight over the top of it. The assassin simply takes an ant whenever it feels hungry, and the body of each victim then adds to its disguise. The giants here too. This is the Moala Moala, the sunfish. It's huge, three meters across, and addicted to lying on its side at the surface. It eats vast quantities of jellyfish. And there are not only fish from me in these waters, there are mammals. sea lions, whose ancestors originally came from the coasts of California. The Galapagos plankton is so abundant it attracts some of the biggest of all ocean mammals, humpback whales, and rivalling them in size the biggest of all fish. 20 ton whale shark. Few parts of the world's oceans can equally as Galapagos waters for sheer variety and abundance. That creature was a penguin. Penguins are ocean-goings for moose. But a few thousand years ago some of them got caught in the cold waters of the Humboldt current and were carried northwards up the coast of South America and out to the Galapagos. They could hardly have found anywhere more different from their polar home and in and the response they chain, the Emperor penguin that lives near the South Pole stands over a metre high, Galapagos penguin is now only half, and that helps a lot in the Galapagos. Small animals lose heat much faster than big ones, and the penguins have developed behavioral tricks as well. Bear feet are easily sunburnt, so they do their best to keep them covered, and some parts of the sea around the islands are quite cool. The humbalt current flowing up from the Antarctic and washing around the western parts of the archipelago is still quite chilly. So most of the penguins stay in the channel between the two westernmost island and when things get really hot, they can still cool off with the swim. They're quick to detect the slightest variation in temperature and move around to find places where an eddy might have brought a pleasing chill. The arrival of penguins must be the most unlikely event in the whole story of the colonization of the Galapagos. The existence of creatures like these so far from the nearest continent poses many questions. How, for example, did these enormous beasts get to the islands in the first place? But perhaps the most extraordinary thing about the Galapagos tortoises is that they're not all the same. islands have different kinds. In the heyday there were 15 species. They seem to have appeared in an evolutionary blink of the eye. But will soon become a leaf. It's no ordinary. It has a special altogether more sinister. This is Nepenthes, the pitcher plant. It grows in nutrient poor soils, So has to find nitrogen and minerals in another way. The leaf, just like a flower, attracts insects with a reward. The pitcher is coloured and scented to appeal to flies looking for a meal of rotting flesh. The visitors are rewarded with a greasy substance on the underside of the pitcher's lid. But the plant wants something in return, not pollen, but a meal. The lip of the pitcher is covered in tiny slippery ridges. Wax lubricates the surface further. It's extremely difficult to hold on, even for a fly. Once inside, there's no escape. The leaf holds a pool of digestive liquid. This contains microscopic elastic filaments, which give it the properties of quicksand. The more the insect struggles, the deeper it sinks. Enzymes begin to dissolve the victim's body while it's still alive.\""
137
- ]
138
- },
139
- "execution_count": 61,
140
- "metadata": {},
141
- "output_type": "execute_result"
142
- }
143
- ],
144
- "source": [
145
- "out"
146
- ]
147
- },
148
- {
149
- "cell_type": "code",
150
- "execution_count": null,
151
- "metadata": {},
152
- "outputs": [],
153
- "source": [
154
- "def transcript(audio):\n",
155
- " if type(audio) == str:\n",
156
- " link_to_audio = audio\n",
157
- " audio = torchaudio.load(link_to_audio)\n",
158
- "\n",
159
- " # We assume that the audio is the audio tensor\n",
160
- "\n",
161
- " # process the audio array\n",
162
- " input_features = processor(audio_array, sampling_rate, return_tensors=\"pt\").input_features\n",
163
- " predicted_ids = modelw.generate(input_features)\n",
164
- "\n",
165
- " transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True)\n",
166
- " \n",
167
- " return audio_path, state['context'], state"
168
- ]
169
- },
170
- {
171
- "cell_type": "code",
172
- "execution_count": null,
173
- "metadata": {},
174
- "outputs": [],
175
- "source": [
176
- "def transcript(general_context, link_to_audio, voice, place, time, delete_history, state):\n",
177
- " \"\"\"this function manages speech-to-text to input Fnanswer function and text-to-speech with the Fnanswer output\"\"\"\n",
178
- " # load audio from a specific path\n",
179
- " audio_path = link_to_audio\n",
180
- " audio_array, sampling_rate = librosa.load(link_to_audio, sr=16000) # \"sr=16000\" ensures that the sampling rate is as required\n",
181
- "\n",
182
- " # process the audio array\n",
183
- " input_features = processor(audio_array, sampling_rate, return_tensors=\"pt\").input_features\n",
184
- " predicted_ids = modelw.generate(input_features)\n",
185
- "\n",
186
- " transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True)\n",
187
- " \n",
188
- "\n",
189
- "\n",
190
- " return audio_path, state['context'], state"
191
- ]
192
- },
193
- {
194
- "cell_type": "code",
195
- "execution_count": 64,
196
- "metadata": {},
197
- "outputs": [
198
- {
199
- "name": "stdout",
200
- "output_type": "stream",
201
- "text": [
202
- "Running on local URL: http://127.0.0.1:7875\n",
203
- "\n",
204
- "To create a public link, set `share=True` in `launch()`.\n"
205
- ]
206
- },
207
- {
208
- "data": {
209
- "text/html": [
210
- "<div><iframe src=\"http://127.0.0.1:7875/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
211
- ],
212
- "text/plain": [
213
- "<IPython.core.display.HTML object>"
214
- ]
215
- },
216
- "metadata": {},
217
- "output_type": "display_data"
218
- },
219
- {
220
- "data": {
221
- "text/plain": []
222
- },
223
- "execution_count": 64,
224
- "metadata": {},
225
- "output_type": "execute_result"
226
- }
227
- ],
228
- "source": [
229
- "import numpy as np\n",
230
- "import gradio as gr\n",
231
- "import torchaudio\n",
232
- "import time\n",
233
- "import torch\n",
234
- "\n",
235
- "def save_audio_as_wav(data, sample_rate, file_path):\n",
236
- " # make a tensor from the numpy array\n",
237
- " data = torch.tensor(data).reshape(1, -1)\n",
238
- " torchaudio.save(file_path, data, sample_rate=sample_rate, bits_per_sample=16, encoding=\"PCM_S\")\n",
239
- "\n",
240
- "def save_and_transcribe_audio(audio):\n",
241
- " # capture the audio and save it to a file as wav or mp3\n",
242
- " # file_name = save(\"audioinput.wav\")\n",
243
- " sr, y = audio\n",
244
- " # y = y.astype(np.float32)\n",
245
- " # y /= np.max(np.abs(y))\n",
246
- "\n",
247
- " # add timestamp to file name\n",
248
- " filename = f\"audio{time.time()}.wav\"\n",
249
- " save_audio_as_wav(y, sr, filename)\n",
250
- " \n",
251
- " sr, y = audio\n",
252
- " y = y.astype(np.float32)\n",
253
- " y /= np.max(np.abs(y))\n",
254
- " text = transcriber({\"sampling_rate\": sr, \"raw\":y})[\"text\"]\n",
255
- " return text\n",
256
- "\n",
257
- "gr.Interface(\n",
258
- " fn=save_and_transcribe_audio, \n",
259
- " inputs=gr.Audio(sources=\"microphone\", type=\"numpy\", label=\"Record Audio\"), \n",
260
- " outputs=\"text\").launch()"
261
- ]
262
- },
263
- {
264
- "cell_type": "code",
265
- "execution_count": null,
266
- "metadata": {},
267
- "outputs": [],
268
- "source": []
269
- }
270
- ],
271
- "metadata": {
272
- "kernelspec": {
273
- "display_name": "llm",
274
- "language": "python",
275
- "name": "python3"
276
- },
277
- "language_info": {
278
- "codemirror_mode": {
279
- "name": "ipython",
280
- "version": 3
281
- },
282
- "file_extension": ".py",
283
- "mimetype": "text/x-python",
284
- "name": "python",
285
- "nbconvert_exporter": "python",
286
- "pygments_lexer": "ipython3",
287
- "version": "3.11.8"
288
- }
289
- },
290
- "nbformat": 4,
291
- "nbformat_minor": 2
292
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
stttotts.py DELETED
@@ -1,177 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- """sttToTts.ipynb
3
-
4
- Automatically generated by Colaboratory.
5
-
6
- Original file is located at
7
- https://colab.research.google.com/drive/15QqRKFSwfhRdnaj5-R1z6xFfeEOOta38
8
- """
9
-
10
- #text-to-speech and speech to text
11
- !pip install TTS
12
- !pip install transformers
13
-
14
- #text to speech
15
- from TTS.api import TTS
16
- tts = TTS("tts_models/multilingual/multi-dataset/your_tts", cs_api_model = "TTS.cs_api.CS_API", gpu=True)
17
-
18
- #voice recording
19
- import IPython.display
20
- import google.colab.output
21
- import base64
22
- # all imports for voice recording
23
- from IPython.display import Javascript
24
- from google.colab import output
25
- from base64 import b64decode
26
-
27
- #to record sound, found on https://gist.github.com/korakot/c21c3476c024ad6d56d5f48b0bca92be
28
-
29
- RECORD = """
30
- const sleep = time => new Promise(resolve => setTimeout(resolve, time))
31
- const b2text = blob => new Promise(resolve => {
32
- const reader = new FileReader()
33
- reader.onloadend = e => resolve(e.srcElement.result)
34
- reader.readAsDataURL(blob)
35
- })
36
- var record = time => new Promise(async resolve => {
37
- stream = await navigator.mediaDevices.getUserMedia({ audio: true })
38
- recorder = new MediaRecorder(stream)
39
- chunks = []
40
- recorder.ondataavailable = e => chunks.push(e.data)
41
- recorder.start()
42
- await sleep(time)
43
- recorder.onstop = async ()=>{
44
- blob = new Blob(chunks)
45
- text = await b2text(blob)
46
- resolve(text)
47
- }
48
- recorder.stop()
49
- })
50
- """
51
-
52
- def record(name, sec):
53
- display(Javascript(RECORD))
54
- s = output.eval_js('record(%d)' % (sec*1000))
55
- b = b64decode(s.split(',')[1])
56
- with open(f'{name}.webm','wb') as f:
57
- f.write(b)
58
- return (f'{name}.webm') # or webm ?
59
-
60
- #to record the text which is going to be transcribed
61
- record('audio', sec = 10)
62
-
63
- #works -- speech-to-text with an audio I provide the path to reach
64
- from transformers import WhisperProcessor, WhisperForConditionalGeneration
65
- import librosa
66
-
67
- # load model and processor
68
- processor = WhisperProcessor.from_pretrained("openai/whisper-small")
69
- model = WhisperForConditionalGeneration.from_pretrained("openai/whisper-small")
70
- model.config.forced_decoder_ids = None
71
-
72
- # load audio from a specific path
73
- audio_path = "audio.webm"
74
- audio_array, sampling_rate = librosa.load(audio_path, sr=16000) # "sr=16000" ensures that the sampling rate is as required
75
-
76
-
77
- # process the audio array
78
- input_features = processor(audio_array, sampling_rate, return_tensors="pt").input_features
79
-
80
-
81
- predicted_ids = model.generate(input_features)
82
-
83
- transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True)
84
- print(transcription)
85
-
86
- #to record the speaker's voice used for tts
87
- record('speaker', sec = 10 )
88
-
89
- #library to convert digits to words (ex : 1 --> one)
90
- import locale
91
- locale.getpreferredencoding = lambda: "UTF-8"
92
- !pip install inflect
93
-
94
- import re
95
- import inflect
96
- #because numbers under digit format are ignored otherwise
97
- def convert_numbers_to_words(s):
98
- p = inflect.engine()
99
- # Find all sequences of digits in the string
100
- numbers = re.findall(r'\d+', s)
101
- for number in numbers:
102
- # Convert each number to words
103
- words = p.number_to_words(number)
104
- # Replace the original number in the string with its word representation
105
- s = s.replace(number, words)
106
- return s
107
-
108
- #model test 1 for text to speech
109
- #works - text to speech with voice cloner (by providing the path to the audio where the voice is)
110
- from google.colab import drive
111
- from IPython.display import Audio
112
-
113
-
114
-
115
- tts.tts_to_file(text=convert_numbers_to_words(str(transcription)),
116
- file_path="output.wav",
117
- speaker_wav='speaker.webm',
118
- language="en",
119
- emotion ='angry',
120
- speed = 2)
121
- audio_path = "output.wav"
122
- Audio(audio_path)
123
-
124
- #model test 2 for text to speech
125
- from IPython.display import Audio
126
- # TTS with on the fly voice conversion
127
- api = TTS("tts_models/deu/fairseq/vits")
128
- api.tts_with_vc_to_file(
129
- text="Wie sage ich auf Italienisch, dass ich dich liebe?",
130
- speaker_wav="speaker.webm",
131
- file_path="ouptut.wav"
132
- )
133
- audio_path = "output.wav"
134
- Audio(audio_path)
135
-
136
- #model test 3 for text to speech
137
- from TTS.api import TTS
138
- tts = TTS("tts_models/multilingual/multi-dataset/xtts_v1", gpu=True)
139
-
140
- from IPython.display import Audio
141
-
142
-
143
- # generate speech by cloning a voice using custom settings
144
- tts.tts_to_file(text="But for me to rap like a computer it must be in my genes I got a laptop in my back pocket My pen'll go off when I half-cock it Got a fat knot from that rap profit Made a livin' and a killin' off it Ever since Bill Clinton was still in office with Monica Lewinsky feelin' on his nutsack I'm an MC still as honest",
145
- file_path="output.wav",
146
- speaker_wav="Slide 1.m4a",
147
- language="en",
148
- emotion = "neutral",
149
- decoder_iterations=35)
150
-
151
- audio_path = "output.wav"
152
- Audio(audio_path)
153
-
154
- # Init TTS with the target studio speaker
155
- tts = TTS(model_name="coqui_studio/en/Torcull Diarmuid/coqui_studio", progress_bar=False)
156
- # Run TTS
157
- tts.tts_to_file(text="This is a test.", file_path=OUTPUT_PATH)
158
- # Run TTS with emotion and speed control
159
- tts.tts_to_file(text="This is a test.", file_path=OUTPUT_PATH, emotion="Happy", speed=1.5)
160
-
161
- #model test 4 for text to speech
162
- from IPython.display import Audio
163
-
164
- from TTS.api import TTS
165
- #api = TTS(model_name="tts_models/eng/fairseq/vits").to("cuda")
166
- #api.tts_to_file("This is a test.", file_path="output.wav")
167
-
168
- # TTS with on the fly voice conversion
169
- api = TTS("tts_models/deu/fairseq/vits")
170
- api.tts_with_vc_to_file(
171
- "I am a basic human",
172
- speaker_wav="speaker.webm",
173
- file_path="output.wav"
174
- )
175
-
176
- audio_path = "output.wav"
177
- Audio(audio_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
test_raven.ipynb DELETED
@@ -1,936 +0,0 @@
1
- {
2
- "cells": [
3
- {
4
- "cell_type": "markdown",
5
- "metadata": {},
6
- "source": [
7
- "### libraries import"
8
- ]
9
- },
10
- {
11
- "cell_type": "code",
12
- "execution_count": 1,
13
- "metadata": {
14
- "collapsed": true,
15
- "id": "oOnNfKjX4IAV"
16
- },
17
- "outputs": [
18
- {
19
- "name": "stderr",
20
- "output_type": "stream",
21
- "text": [
22
- "/opt/conda/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
23
- " from .autonotebook import tqdm as notebook_tqdm\n",
24
- "/opt/conda/lib/python3.10/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",
25
- " _torch_pytree._register_pytree_node(\n",
26
- "/opt/conda/lib/python3.10/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",
27
- " _torch_pytree._register_pytree_node(\n",
28
- "/opt/conda/lib/python3.10/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",
29
- " _torch_pytree._register_pytree_node(\n"
30
- ]
31
- }
32
- ],
33
- "source": [
34
- "import os\n",
35
- "\n",
36
- "#gradio interface\n",
37
- "import gradio as gr\n",
38
- "\n",
39
- "from transformers import AutoModelForCausalLM,AutoTokenizer\n",
40
- "import torch\n",
41
- "\n",
42
- "#STT (speech to text)\n",
43
- "from transformers import WhisperProcessor, WhisperForConditionalGeneration\n",
44
- "import librosa\n",
45
- "\n",
46
- "#TTS (text to speech)\n",
47
- "import torch\n",
48
- "from TTS.api import TTS\n",
49
- "from IPython.display import Audio\n",
50
- "\n",
51
- "#json request for APIs\n",
52
- "import requests\n",
53
- "import json\n",
54
- "\n",
55
- "#regular expressions\n",
56
- "import re\n",
57
- "\n",
58
- "#langchain and function calling\n",
59
- "from typing import List, Literal, Union\n",
60
- "import requests\n",
61
- "from functools import partial\n",
62
- "import math\n",
63
- "\n",
64
- "\n",
65
- "#langchain, not used anymore since I had to find another way fast to stop using the endpoint, but could be interesting to reuse \n",
66
- "from langchain.tools.base import StructuredTool\n",
67
- "from langchain.agents import (\n",
68
- " Tool,\n",
69
- " AgentExecutor,\n",
70
- " LLMSingleActionAgent,\n",
71
- " AgentOutputParser,\n",
72
- ")\n",
73
- "from langchain.schema import AgentAction, AgentFinish, OutputParserException\n",
74
- "from langchain.prompts import StringPromptTemplate\n",
75
- "from langchain.llms import HuggingFaceTextGenInference\n",
76
- "from langchain.chains import LLMChain\n",
77
- "\n",
78
- "\n",
79
- "\n",
80
- "from datetime import datetime, timedelta, timezone\n",
81
- "from transformers import pipeline\n",
82
- "import inspect"
83
- ]
84
- },
85
- {
86
- "cell_type": "code",
87
- "execution_count": 7,
88
- "metadata": {},
89
- "outputs": [],
90
- "source": [
91
- "from apis import *"
92
- ]
93
- },
94
- {
95
- "cell_type": "markdown",
96
- "metadata": {},
97
- "source": [
98
- "### Models loads"
99
- ]
100
- },
101
- {
102
- "cell_type": "code",
103
- "execution_count": 2,
104
- "metadata": {},
105
- "outputs": [
106
- {
107
- "name": "stderr",
108
- "output_type": "stream",
109
- "text": [
110
- "Special tokens have been added in the vocabulary, make sure the associated word embeddings are fine-tuned or trained.\n",
111
- "Loading checkpoint shards: 100%|██████████| 3/3 [00:10<00:00, 3.45s/it]\n"
112
- ]
113
- }
114
- ],
115
- "source": [
116
- "#NexusRaven for function calling\n",
117
- "model_id = \"Nexusflow/NexusRaven-13B\"\n",
118
- "tokenizer = AutoTokenizer.from_pretrained(model_id)\n",
119
- "modelNexus = AutoModelForCausalLM.from_pretrained(model_id, device_map=0, load_in_4bit=True)\n",
120
- "pipe = pipeline(\"text-generation\", model=modelNexus, tokenizer = tokenizer)"
121
- ]
122
- },
123
- {
124
- "cell_type": "markdown",
125
- "metadata": {},
126
- "source": [
127
- "## Function calling with NexusRaven "
128
- ]
129
- },
130
- {
131
- "cell_type": "code",
132
- "execution_count": 3,
133
- "metadata": {},
134
- "outputs": [],
135
- "source": [
136
- "# load api key from .env file\n",
137
- "# weather api and tomtom api key\n",
138
- "from dotenv import load_dotenv\n",
139
- "load_dotenv()\n",
140
- "WHEATHER_API_KEY = os.getenv(\"WEATHER_API_KEY\")\n",
141
- "TOMTOM_KEY = os.getenv(\"TOMTOM_API_KEY\")"
142
- ]
143
- },
144
- {
145
- "cell_type": "code",
146
- "execution_count": 19,
147
- "metadata": {},
148
- "outputs": [],
149
- "source": [
150
- "#FUNCTION CALLING \n",
151
- "\n",
152
- "##########################################################\n",
153
- "# Step 1: Define the functions you want to articulate. ###\n",
154
- "##########################################################\n",
155
- "\n",
156
- "# apis.py\n",
157
- "\n",
158
- "\n",
159
- "#############################################################\n",
160
- "# Step 2: Let's define some utils for building the prompt ###\n",
161
- "#############################################################\n",
162
- "\n",
163
- "\n",
164
- "def format_functions_for_prompt(*functions):\n",
165
- " formatted_functions = []\n",
166
- " for func in functions:\n",
167
- " source_code = inspect.getsource(func)\n",
168
- " # Get function name\n",
169
- " function_name = func.__name__\n",
170
- " # Get function signature\n",
171
- " signature = inspect.signature(func)\n",
172
- " docstring = inspect.getdoc(func)\n",
173
- " formatted_functions.append(\n",
174
- " f\"OPTION:\\n<func_start>{function_name}{signature}<func_end>\\n<docstring_start>\\n{docstring}\\n<docstring_end>\"\n",
175
- " )\n",
176
- " return \"\\n\".join(formatted_functions)\n",
177
- "\n",
178
- "\n",
179
- "##############################\n",
180
- "# Step 3: Construct Prompt ###\n",
181
- "##############################\n",
182
- "\n",
183
- "\n",
184
- "def construct_prompt(user_query: str, context):\n",
185
- " formatted_prompt = format_functions_for_prompt(get_weather, find_points_of_interest, find_route, get_forecast, search_along_route)\n",
186
- " formatted_prompt += f'\\n\\nContext : {context}'\n",
187
- " formatted_prompt += f\"\\n\\nUser Query: Question: {user_query}\\n\"\n",
188
- "\n",
189
- " prompt = (\n",
190
- " \"<human>:\\n\"\n",
191
- " + formatted_prompt\n",
192
- " + \"Please pick a function from the above options that best answers the user query and fill in the appropriate arguments.<human_end>\"\n",
193
- " )\n",
194
- " return prompt\n",
195
- "\n",
196
- "#######################################\n",
197
- "# Step 4: Execute the function call ###\n",
198
- "#######################################\n",
199
- "\n",
200
- "\n",
201
- "def execute_function_call(model_output):\n",
202
- " # Ignore everything after \"Reflection\" since that is not essential.\n",
203
- " function_call = (\n",
204
- " model_output[0][\"generated_text\"]\n",
205
- " .strip()\n",
206
- " .split(\"\\n\")[1]\n",
207
- " .replace(\"Initial Answer:\", \"\")\n",
208
- " .strip()\n",
209
- " )\n",
210
- "\n",
211
- " try:\n",
212
- " return eval(function_call)\n",
213
- " except Exception as e:\n",
214
- " return str(e)\n"
215
- ]
216
- },
217
- {
218
- "cell_type": "code",
219
- "execution_count": 20,
220
- "metadata": {},
221
- "outputs": [],
222
- "source": [
223
- "# convert bytes to megabytes\n",
224
- "def get_cuda_usage(): return round(torch.cuda.memory_allocated(\"cuda:0\")/1024/1024,2)"
225
- ]
226
- },
227
- {
228
- "cell_type": "code",
229
- "execution_count": 21,
230
- "metadata": {},
231
- "outputs": [],
232
- "source": [
233
- "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"
234
- ]
235
- },
236
- {
237
- "cell_type": "code",
238
- "execution_count": 22,
239
- "metadata": {},
240
- "outputs": [
241
- {
242
- "name": "stdout",
243
- "output_type": "stream",
244
- "text": [
245
- "<human>:\n",
246
- "OPTION:\n",
247
- "<func_start>get_weather(city_name: str = '', **kwargs)<func_end>\n",
248
- "<docstring_start>\n",
249
- "Returns the CURRENT weather in a specified city.\n",
250
- "Args:\n",
251
- "city_name (string) : Required. The name of the city.\n",
252
- "<docstring_end>\n",
253
- "OPTION:\n",
254
- "<func_start>find_points_of_interest(lat='0', lon='0', city='', type_of_poi='restaurant', **kwargs)<func_end>\n",
255
- "<docstring_start>\n",
256
- "Return some of the closest points of interest for a specific location and type of point of interest. The more parameters there are, the more precise.\n",
257
- ":param lat (string): latitude\n",
258
- ":param lon (string): longitude\n",
259
- ":param city (string): Required. city\n",
260
- ":param type_of_poi (string): Required. type of point of interest depending on what the user wants to do.\n",
261
- "<docstring_end>\n",
262
- "OPTION:\n",
263
- "<func_start>find_route(lat_depart='0', lon_depart='0', city_depart='', address_destination='', depart_time='', **kwargs)<func_end>\n",
264
- "<docstring_start>\n",
265
- "Return the distance and the estimated time to go to a specific destination from the current place, at a specified depart time.\n",
266
- ":param lat_depart (string): latitude of depart\n",
267
- ":param lon_depart (string): longitude of depart\n",
268
- ":param city_depart (string): Required. city of depart\n",
269
- ":param address_destination (string): Required. The destination\n",
270
- ":param depart_time (string): departure hour, in the format '08:00:20'.\n",
271
- "<docstring_end>\n",
272
- "OPTION:\n",
273
- "<func_start>get_forecast(city_name: str = '', when=0, **kwargs)<func_end>\n",
274
- "<docstring_start>\n",
275
- "Returns the weather forecast in a specified number of days for a specified city .\n",
276
- "Args:\n",
277
- "city_name (string) : Required. The name of the city.\n",
278
- "when (int) : Required. in number of days (until the day for which we want to know the forecast) (example: tomorrow is 1, in two days is 2, etc.)\n",
279
- "<docstring_end>\n",
280
- "OPTION:\n",
281
- "<func_start>search_along_route(latitude_depart, longitude_depart, city_destination, type_of_poi)<func_end>\n",
282
- "<docstring_start>\n",
283
- "Return some of the closest points of interest along the route from the depart point, specified by its coordinates and a city destination.\n",
284
- ":param latitude_depart (string): Required. Latitude of depart location\n",
285
- ":param longitude_depart (string): Required. Longitude of depart location\n",
286
- ":param city_destination (string): Required. City destination\n",
287
- ":param type_of_poi (string): Required. type of point of interest depending on what the user wants to do.\n",
288
- "<docstring_end>\n",
289
- "\n",
290
- "Context : \n",
291
- "\n",
292
- "User Query: Question: What restaurants are there on the road from Luxembourg Gare, which coordinates are lat 49.5999681, lon 6.1342493, to Thionville?\n",
293
- "Please pick a function from the above options that best answers the user query and fill in the appropriate arguments.<human_end>\n"
294
- ]
295
- }
296
- ],
297
- "source": [
298
- "print(prompt)"
299
- ]
300
- },
301
- {
302
- "cell_type": "code",
303
- "execution_count": 23,
304
- "metadata": {},
305
- "outputs": [
306
- {
307
- "name": "stderr",
308
- "output_type": "stream",
309
- "text": [
310
- "Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.\n"
311
- ]
312
- }
313
- ],
314
- "source": [
315
- "model_output = pipe(\n",
316
- " prompt, do_sample=False, max_new_tokens=3000, return_full_text=False\n",
317
- ")"
318
- ]
319
- },
320
- {
321
- "cell_type": "code",
322
- "execution_count": 24,
323
- "metadata": {},
324
- "outputs": [
325
- {
326
- "name": "stdout",
327
- "output_type": "stream",
328
- "text": [
329
- " \n",
330
- " 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",
331
- "Initial Answer: search_along_route(49.5999681, 6.1342493, 'Thionville','restaurant')\n",
332
- "Reflection: The search_along_route function takes in four arguments: latitude_depart, longitude_depart, city_destination, and type_of_poi.\n",
333
- "\n",
334
- "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",
335
- "\n",
336
- "The call provided is search_along_route(49.5999681, 6.1342493, 'Thionville','restaurant').\n",
337
- "\n",
338
- "The call can be improved because the function requires the latitude and longitude of the depart point, which are not provided.\n",
339
- "\n",
340
- "The correct call would be search_along_route(latitude_depart = 49.5999681, longitude_depart = 6.1342493, city_destination = 'Thionville', type_of_poi ='restaurant').\n",
341
- "\n",
342
- "This call would return some of the closest points of interest along the route from the depart point, specified by its coordinates and a city destination.\n",
343
- "\n",
344
- "Therefore, the argument chosen for the latitude_depart and longitude_depart is 49.5999681 and 6.1342493, respectively.\n",
345
- "\n",
346
- "This call can be run:\n",
347
- "Fixed Call: search_along_route(latitude_depart = 49.5999681, longitude_depart = 6.1342493, city_destination = 'Thionville', type_of_poi ='restaurant')\n",
348
- "Fixed Function Name: search_along_route\n",
349
- "Fixed Function Args: {\"latitude_depart\" : 49.5999681, \"longitude_depart\" : 6.1342493, \"city_destination\" : 'Thionville', \"type_of_poi\" :'restaurant'}\n",
350
- "\n",
351
- "Done.\n"
352
- ]
353
- }
354
- ],
355
- "source": [
356
- "print(model_output[0][\"generated_text\"])"
357
- ]
358
- },
359
- {
360
- "cell_type": "code",
361
- "execution_count": 8,
362
- "metadata": {
363
- "collapsed": true
364
- },
365
- "outputs": [
366
- {
367
- "name": "stderr",
368
- "output_type": "stream",
369
- "text": [
370
- "Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.\n"
371
- ]
372
- },
373
- {
374
- "name": "stdout",
375
- "output_type": "stream",
376
- "text": [
377
- "before everything: 7802.67\n",
378
- "after creating prompt: 7802.67\n"
379
- ]
380
- },
381
- {
382
- "name": "stderr",
383
- "output_type": "stream",
384
- "text": [
385
- "/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",
386
- " 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"
387
- ]
388
- },
389
- {
390
- "name": "stdout",
391
- "output_type": "stream",
392
- "text": [
393
- " \n",
394
- " 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",
395
- "Initial Answer: search_along_route(49.5999681, 6.1342493, 'Thionville','restaurant')\n",
396
- "Reflection: The search_along_route function takes in four arguments: latitude_depart, longitude_depart, city_destination, and type_of_poi.\n",
397
- "\n",
398
- "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",
399
- "\n",
400
- "The call provided is search_along_route(49.5999681, 6.1342493, 'Thionville','restaurant').\n",
401
- "\n",
402
- "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",
403
- "\n",
404
- "The correct call would be\n"
405
- ]
406
- }
407
- ],
408
- "source": [
409
- "# might be deleted\n",
410
- "# Compute a Simple equation\n",
411
- "print(f\"before everything: {get_cuda_usage()}\")\n",
412
- "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",
413
- "print(f\"after creating prompt: {get_cuda_usage()}\")\n",
414
- "model_output = pipe(\n",
415
- " prompt, do_sample=False, max_new_tokens=300, return_full_text=False\n",
416
- " )\n",
417
- "print(model_output[0][\"generated_text\"])\n",
418
- "#execute_function_call(pipe(construct_prompt(\"Is it raining in Belval, ?\"), do_sample=False, max_new_tokens=300, return_full_text=False))"
419
- ]
420
- },
421
- {
422
- "cell_type": "code",
423
- "execution_count": 12,
424
- "metadata": {},
425
- "outputs": [
426
- {
427
- "name": "stdout",
428
- "output_type": "stream",
429
- "text": [
430
- "creating the pipe of model output: 13736.26\n",
431
- "49.3579272\n",
432
- "after execute function call: 13736.26\n",
433
- "after garbage collect and empty_cache: 13736.26\n"
434
- ]
435
- }
436
- ],
437
- "source": [
438
- "print(f\"creating the pipe of model output: {get_cuda_usage()}\")\n",
439
- "result = execute_function_call(model_output)\n",
440
- "print(f\"after execute function call: {get_cuda_usage()}\")\n",
441
- "del model_output\n",
442
- "import gc # garbage collect library\n",
443
- "gc.collect()\n",
444
- "torch.cuda.empty_cache() \n",
445
- "print(f\"after garbage collect and empty_cache: {get_cuda_usage()}\")\n",
446
- "#print(\"Model Output:\", model_output)\n",
447
- "# print(\"Execution Result:\", result)"
448
- ]
449
- },
450
- {
451
- "cell_type": "markdown",
452
- "metadata": {},
453
- "source": [
454
- "## functions to process the anwser and the question"
455
- ]
456
- },
457
- {
458
- "cell_type": "code",
459
- "execution_count": 13,
460
- "metadata": {},
461
- "outputs": [],
462
- "source": [
463
- "#generation of text with Stable beluga \n",
464
- "def gen(p, maxlen=15, sample=True):\n",
465
- " toks = tokr(p, return_tensors=\"pt\")\n",
466
- " res = model.generate(**toks.to(\"cuda\"), max_new_tokens=maxlen, do_sample=sample).to('cpu')\n",
467
- " return tokr.batch_decode(res)\n",
468
- "\n",
469
- "#to have a prompt corresponding to the specific format required by the fine-tuned model Stable Beluga\n",
470
- "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\""
471
- ]
472
- },
473
- {
474
- "cell_type": "code",
475
- "execution_count": 14,
476
- "metadata": {
477
- "id": "yAJI0WyOLE8G"
478
- },
479
- "outputs": [],
480
- "source": [
481
- "def car_answer_only(complete_answer, general_context):\n",
482
- " \"\"\"returns only the AI assistant answer, without all context, to reply to the user\"\"\"\n",
483
- " pattern = r\"Assistant:\\\\n(.*)(</s>|[.!?](\\s|$))\" #pattern = r\"Assistant:\\\\n(.*?)</s>\"\n",
484
- "\n",
485
- " match = re.search(pattern, complete_answer, re.DOTALL)\n",
486
- "\n",
487
- " if match:\n",
488
- " # Extracting the text\n",
489
- " model_answer = match.group(1)\n",
490
- " #print(complete_answer)\n",
491
- " else:\n",
492
- " #print(complete_answer)\n",
493
- " model_answer = \"There has been an error with the generated response.\" \n",
494
- "\n",
495
- " general_context += model_answer\n",
496
- " return (model_answer, general_context)\n",
497
- "#print(model_answer)"
498
- ]
499
- },
500
- {
501
- "cell_type": "code",
502
- "execution_count": 15,
503
- "metadata": {
504
- "id": "ViCEgogaENNV"
505
- },
506
- "outputs": [],
507
- "source": [
508
- "def FnAnswer(general_context, ques, place, time, delete_history, state):\n",
509
- " \"\"\"function to manage the two different llms (function calling and basic answer) and call them one after the other\"\"\"\n",
510
- " # Initialize state if it is None\n",
511
- " if delete_history == \"Yes\":\n",
512
- " state = None\n",
513
- " if state is None:\n",
514
- " conv_context = []\n",
515
- " conv_context.append(general_context)\n",
516
- " state = {}\n",
517
- " state['context'] = conv_context\n",
518
- " state['number'] = 0\n",
519
- " state['last_question'] = \"\"\n",
520
- " \n",
521
- " if type(ques) != str: \n",
522
- " ques = ques[0]\n",
523
- " \n",
524
- " place = definePlace(place) #which on the predefined places it is\n",
525
- " \n",
526
- " formatted_context = '\\n'.join(state['context'])\n",
527
- " \n",
528
- " #updated at every question\n",
529
- " general_context = f\"\"\"\n",
530
- " Recent conversation history: '{formatted_context}' (If empty, this indicates the beginning of the conversation).\n",
531
- "\n",
532
- " Previous question from the user: '{state['last_question']}' (This may or may not be related to the current question).\n",
533
- "\n",
534
- " 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",
535
- "\n",
536
- " \"\"\"\n",
537
- " #first llm call (function calling model, NexusRaven)\n",
538
- " model_output= pipe(construct_prompt(ques, general_context), do_sample=False, max_new_tokens=300, return_full_text=False)\n",
539
- " call = execute_function_call(model_output) #call variable is formatted to as a call to a specific function with the required parameters\n",
540
- " print(call)\n",
541
- " #this is what will erase the model_output from the GPU memory to free up space\n",
542
- " del model_output\n",
543
- " import gc # garbage collect library\n",
544
- " gc.collect()\n",
545
- " torch.cuda.empty_cache() \n",
546
- " \n",
547
- " #updated at every question\n",
548
- " 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",
549
- " \n",
550
- " #question formatted for the StableBeluga llm (second llm), using the output of the first llm as context in general_context\n",
551
- " question=f\"\"\"Reply to the user and answer any question with the help of the provided context.\n",
552
- "\n",
553
- " ## Context\n",
554
- "\n",
555
- " {general_context} .\n",
556
- "\n",
557
- " ## Question\n",
558
- "\n",
559
- " {ques}\"\"\"\n",
560
- "\n",
561
- " complete_answer = str(gen(mk_prompt(question), 100)) #answer generation with StableBeluga (2nd llm)\n",
562
- "\n",
563
- " model_answer, general_context= car_answer_only(complete_answer, general_context) #to retrieve only the car answer \n",
564
- " \n",
565
- " 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",
566
- " \n",
567
- " state['last_question'] = ques #add the current question as 'last question' for the next question's context\n",
568
- " \n",
569
- " state['number']= state['number'] + 1 #adds 1 to the number of interactions with the car\n",
570
- "\n",
571
- " state['context'].append(str(state['number']) + '. User question: '+ ques + ', Model answer: ' + model_answer) #modifies the context\n",
572
- " \n",
573
- " #print(\"contexte : \" + '\\n'.join(state['context']))\n",
574
- " \n",
575
- " if len(state['context'])>5: #6 questions maximum in the context to avoid having too many information\n",
576
- " state['context'] = state['context'][1:]\n",
577
- "\n",
578
- " return model_answer, state['context'], state, language"
579
- ]
580
- },
581
- {
582
- "cell_type": "code",
583
- "execution_count": 16,
584
- "metadata": {
585
- "id": "9WQlYePVLrTN"
586
- },
587
- "outputs": [],
588
- "source": [
589
- "def transcript(general_context, link_to_audio, voice, place, time, delete_history, state):\n",
590
- " \"\"\"this function manages speech-to-text to input Fnanswer function and text-to-speech with the Fnanswer output\"\"\"\n",
591
- " # load audio from a specific path\n",
592
- " audio_path = link_to_audio\n",
593
- " audio_array, sampling_rate = librosa.load(link_to_audio, sr=16000) # \"sr=16000\" ensures that the sampling rate is as required\n",
594
- "\n",
595
- "\n",
596
- " # process the audio array\n",
597
- " input_features = processor(audio_array, sampling_rate, return_tensors=\"pt\").input_features\n",
598
- "\n",
599
- "\n",
600
- " predicted_ids = modelw.generate(input_features)\n",
601
- "\n",
602
- " transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True)\n",
603
- "\n",
604
- " quest_processing = FnAnswer(general_context, transcription, place, time, delete_history, state)\n",
605
- " \n",
606
- " state=quest_processing[2]\n",
607
- " \n",
608
- " print(\"langue \" + quest_processing[3])\n",
609
- "\n",
610
- " tts.tts_to_file(text= str(quest_processing[0]),\n",
611
- " file_path=\"output.wav\",\n",
612
- " speaker_wav=f'Audio_Files/{voice}.wav',\n",
613
- " language=quest_processing[3],\n",
614
- " emotion = \"angry\")\n",
615
- "\n",
616
- " audio_path = \"output.wav\"\n",
617
- " return audio_path, state['context'], state"
618
- ]
619
- },
620
- {
621
- "cell_type": "code",
622
- "execution_count": 17,
623
- "metadata": {},
624
- "outputs": [],
625
- "source": [
626
- "def definePlace(place):\n",
627
- " if(place == 'Luxembourg Gare, Luxembourg'):\n",
628
- " return('Luxembourg Gare', '49.5999681', '6.1342493' )\n",
629
- " elif (place =='Kirchberg Campus, Kirchberg'):\n",
630
- " return('Kirchberg Campus, Luxembourg', '49.62571206478235', '6.160082636815114')\n",
631
- " elif (place =='Belval Campus, Belval'):\n",
632
- " return('Belval-Université, Esch-sur-Alzette', '49.499531', '5.9462903')\n",
633
- " elif (place =='Eiffel Tower, Paris'):\n",
634
- " return('Eiffel Tower, Paris', '48.8582599', '2.2945006')\n",
635
- " elif (place=='Thionville, France'):\n",
636
- " return('Thionville, France', '49.357927', '6.167587')"
637
- ]
638
- },
639
- {
640
- "cell_type": "markdown",
641
- "metadata": {},
642
- "source": [
643
- "## Interfaces (text and audio)"
644
- ]
645
- },
646
- {
647
- "cell_type": "code",
648
- "execution_count": 18,
649
- "metadata": {
650
- "collapsed": true
651
- },
652
- "outputs": [
653
- {
654
- "name": "stdout",
655
- "output_type": "stream",
656
- "text": [
657
- "\n",
658
- "Running on local URL: http://0.0.0.0:7860\n",
659
- "\n",
660
- "Could not create share link. Please check your internet connection or our status page: https://status.gradio.app.\n"
661
- ]
662
- },
663
- {
664
- "name": "stderr",
665
- "output_type": "stream",
666
- "text": [
667
- "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"
668
- ]
669
- },
670
- {
671
- "data": {
672
- "text/html": [
673
- "<div><iframe src=\"http://localhost:7860/\" width=\"100%\" height=\"500\" allow=\"autoplay; camera; microphone; clipboard-read; clipboard-write;\" frameborder=\"0\" allowfullscreen></iframe></div>"
674
- ],
675
- "text/plain": [
676
- "<IPython.core.display.HTML object>"
677
- ]
678
- },
679
- "metadata": {},
680
- "output_type": "display_data"
681
- },
682
- {
683
- "name": "stdout",
684
- "output_type": "stream",
685
- "text": [
686
- "Keyboard interruption in main thread... closing server.\n",
687
- "Killing tunnel 0.0.0.0:7860 <> None\n"
688
- ]
689
- },
690
- {
691
- "data": {
692
- "text/plain": []
693
- },
694
- "execution_count": 18,
695
- "metadata": {},
696
- "output_type": "execute_result"
697
- }
698
- ],
699
- "source": [
700
- "#INTERFACE WITH ONLY TEXT\n",
701
- "\n",
702
- "# Generate options for hours (00-23) \n",
703
- "hour_options = [f\"{i:02d}:00:00\" for i in range(24)]\n",
704
- "\n",
705
- "model_answer= ''\n",
706
- "general_context= ''\n",
707
- "# Define the initial state with some initial context.\n",
708
- "print(general_context)\n",
709
- "initial_state = {'context': general_context}\n",
710
- "initial_context= initial_state['context']\n",
711
- "# Create the Gradio interface.\n",
712
- "iface = gr.Interface(\n",
713
- " fn=FnAnswer,\n",
714
- " inputs=[\n",
715
- " gr.Textbox(value=initial_context, visible=False),\n",
716
- " gr.Textbox(lines=2, placeholder=\"Type your message here...\"),\n",
717
- " 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",
718
- " gr.Dropdown(choices=hour_options, label=\"What time is it?\", value = \"08:00:00\"),\n",
719
- " gr.Radio([\"Yes\", \"No\"], label=\"Delete the conversation history?\", value = 'No'),\n",
720
- " gr.State() # This will keep track of the context state across interactions.\n",
721
- " ],\n",
722
- " outputs=[\n",
723
- " gr.Textbox(),\n",
724
- " gr.Textbox(visible=False),\n",
725
- " gr.State()\n",
726
- " ]\n",
727
- ")\n",
728
- "gr.close_all()\n",
729
- "# Launch the interface.\n",
730
- "iface.launch(debug=True, share=True, server_name=\"0.0.0.0\", server_port=7860)\n",
731
- "#contextual=gr.Textbox(value=general_context, visible=False)\n",
732
- "#demo = gr.Interface(fn=FnAnswer, inputs=[contextual,\"text\"], outputs=[\"text\", contextual])\n",
733
- "\n",
734
- "#demo.launch()"
735
- ]
736
- },
737
- {
738
- "cell_type": "code",
739
- "execution_count": 69,
740
- "metadata": {
741
- "collapsed": true,
742
- "id": "mZTt3y3_KOOF"
743
- },
744
- "outputs": [
745
- {
746
- "name": "stdout",
747
- "output_type": "stream",
748
- "text": [
749
- "\n",
750
- "Closing server running on port: 7860\n",
751
- "Closing server running on port: 7860\n",
752
- "Closing server running on port: 7860\n",
753
- "Closing server running on port: 7860\n",
754
- "Closing server running on port: 7860\n",
755
- "Closing server running on port: 7860\n",
756
- "Closing server running on port: 7860\n",
757
- "Closing server running on port: 7860\n",
758
- "Closing server running on port: 7860\n",
759
- "Closing server running on port: 7860\n",
760
- "Running on local URL: http://0.0.0.0:7860\n"
761
- ]
762
- },
763
- {
764
- "ename": "KeyboardInterrupt",
765
- "evalue": "",
766
- "output_type": "error",
767
- "traceback": [
768
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
769
- "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)",
770
- "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",
771
- "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",
772
- "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",
773
- "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",
774
- "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",
775
- "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",
776
- "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",
777
- "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",
778
- "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",
779
- "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",
780
- "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",
781
- "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",
782
- "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",
783
- "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",
784
- "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",
785
- "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",
786
- "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",
787
- "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",
788
- "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",
789
- "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",
790
- "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",
791
- "\u001b[0;31mKeyboardInterrupt\u001b[0m: "
792
- ]
793
- }
794
- ],
795
- "source": [
796
- "#INTERFACE WITH AUDIO TO AUDIO\n",
797
- "\n",
798
- "#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",
799
- "#in \"Insecure origins treated as secure\", enable it and relaunch chrome\n",
800
- "\n",
801
- "#example question: \n",
802
- "# what's the weather like outside?\n",
803
- "# What's the closest restaurant from here?\n",
804
- "\n",
805
- "\n",
806
- "\n",
807
- "# Generate options for hours (00-23) \n",
808
- "hour_options = [f\"{i:02d}:00:00\" for i in range(24)]\n",
809
- "\n",
810
- "model_answer= ''\n",
811
- "general_context= ''\n",
812
- "# Define the initial state with some initial context.\n",
813
- "print(general_context)\n",
814
- "initial_state = {'context': general_context}\n",
815
- "initial_context= initial_state['context']\n",
816
- "# Create the Gradio interface.\n",
817
- "iface = gr.Interface(\n",
818
- " fn=transcript,\n",
819
- " inputs=[\n",
820
- " gr.Textbox(value=initial_context, visible=False),\n",
821
- " gr.Audio( type='filepath', label = 'input audio'),\n",
822
- " gr.Radio(choices=['Donald Trump', 'Eddie Murphy'], label='Choose a voice', value= 'Donald Trump', show_label=True), # Radio button for voice selection\n",
823
- " 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",
824
- " gr.Dropdown(choices=hour_options, label=\"What time is it?\", value = \"08:00:00\"),\n",
825
- " gr.Radio([\"Yes\", \"No\"], label=\"Delete the conversation history?\", value = 'No'),\n",
826
- " gr.State() # This will keep track of the context state across interactions.\n",
827
- " ],\n",
828
- " outputs=[\n",
829
- " gr.Audio(label = 'output audio'),\n",
830
- " gr.Textbox(visible=False),\n",
831
- " gr.State()\n",
832
- " ]\n",
833
- ")\n",
834
- "#close all interfaces open to make the port available\n",
835
- "gr.close_all()\n",
836
- "# Launch the interface.\n",
837
- "iface.launch(debug=True, share=True, server_name=\"0.0.0.0\", server_port=7860, ssl_verify=False)"
838
- ]
839
- },
840
- {
841
- "cell_type": "markdown",
842
- "metadata": {},
843
- "source": [
844
- "## Other possible APIs to use"
845
- ]
846
- },
847
- {
848
- "cell_type": "code",
849
- "execution_count": 80,
850
- "metadata": {},
851
- "outputs": [
852
- {
853
- "ename": "JSONDecodeError",
854
- "evalue": "Expecting value: line 1 column 1 (char 0)",
855
- "output_type": "error",
856
- "traceback": [
857
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
858
- "\u001b[0;31mJSONDecodeError\u001b[0m Traceback (most recent call last)",
859
- "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",
860
- "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",
861
- "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",
862
- "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",
863
- "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting value: line 1 column 1 (char 0)",
864
- "\nDuring handling of the above exception, another exception occurred:\n",
865
- "\u001b[0;31mJSONDecodeError\u001b[0m Traceback (most recent call last)",
866
- "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",
867
- "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",
868
- "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",
869
- "\u001b[0;31mJSONDecodeError\u001b[0m: Expecting value: line 1 column 1 (char 0)"
870
- ]
871
- }
872
- ],
873
- "source": [
874
- "\n",
875
- "def search_nearby(lat, lon, city, key):\n",
876
- " \"\"\"\n",
877
- " :param lat: latitude\n",
878
- " :param lon: longitude\n",
879
- " :param key: api key\n",
880
- " :param type: type of poi\n",
881
- " :return: [5] results ['poi']['name']/['freeformAddress'] || ['position']['lat']/['lon']\n",
882
- " \"\"\"\n",
883
- " results = []\n",
884
- "\n",
885
- " r = requests.get('https://api.tomtom.com/search/2/nearbySearch/.json?key={0}&lat={1}&lon={2}&radius=10000&limit=50'.format(\n",
886
- " key,\n",
887
- " lat,\n",
888
- " lon\n",
889
- " ))\n",
890
- "\n",
891
- " for result in r.json()['results']:\n",
892
- " results.append(f\"The {' '.join(result['poi']['categories'])} {result['poi']['name']} is {int(result['dist'])} meters far from {city}\")\n",
893
- " if len(results) == 7:\n",
894
- " break\n",
895
- "\n",
896
- " return \". \".join(results)\n",
897
- "\n",
898
- "\n",
899
- "print(search_nearby('49.625892805337514', '6.160417066963513', 'your location', TOMTOM_KEY))"
900
- ]
901
- },
902
- {
903
- "cell_type": "code",
904
- "execution_count": null,
905
- "metadata": {},
906
- "outputs": [],
907
- "source": []
908
- }
909
- ],
910
- "metadata": {
911
- "accelerator": "GPU",
912
- "colab": {
913
- "gpuType": "T4",
914
- "provenance": []
915
- },
916
- "kernelspec": {
917
- "display_name": "Python 3 (ipykernel)",
918
- "language": "python",
919
- "name": "python3"
920
- },
921
- "language_info": {
922
- "codemirror_mode": {
923
- "name": "ipython",
924
- "version": 3
925
- },
926
- "file_extension": ".py",
927
- "mimetype": "text/x-python",
928
- "name": "python",
929
- "nbconvert_exporter": "python",
930
- "pygments_lexer": "ipython3",
931
- "version": "3.10.13"
932
- }
933
- },
934
- "nbformat": 4,
935
- "nbformat_minor": 1
936
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
tts.ipynb DELETED
The diff for this file is too large to render. See raw diff