Frazer2810 commited on
Commit
6eb8def
·
verified ·
1 Parent(s): 57a48f1

Update agent.py

Browse files
Files changed (1) hide show
  1. agent.py +77 -53
agent.py CHANGED
@@ -1,51 +1,62 @@
1
  import os
2
  import openai
3
  import wikipedia
4
- from duckduckgo_search import DDGS
5
  import arxiv
6
  import json
7
  import re
8
 
9
- # Carica la chiave API di OpenAI dalla variabile d'ambiente
10
  # Per i test locali, puoi usare python-dotenv e un file .env
11
  # from dotenv import load_dotenv
12
  # load_dotenv()
13
- # openai.api_key = os.getenv("OPENAI_API_KEY") # La libreria OpenAI >1.0.0 lo gestisce automaticamente
14
 
15
- # Se la chiave API non è impostata tramite variabile d'ambiente,
16
- # la libreria OpenAI cercherà di trovarla.
17
- # È buona pratica assicurarsi che sia disponibile.
 
 
18
  if not os.getenv("OPENAI_API_KEY"):
19
  print("ATTENZIONE: La variabile d'ambiente OPENAI_API_KEY non è impostata.")
20
  print("L'agente potrebbe non funzionare correttamente senza una chiave API OpenAI valida.")
21
 
 
 
 
 
22
 
23
  MAX_WIKIPEDIA_RESULTS = 3
24
- MAX_DDG_RESULTS = 4
25
  MAX_ARXIV_RESULTS = 3
26
- MAX_TOOL_ITERATIONS = 7 # Numero massimo di cicli di chiamata agli strumenti
27
 
28
  class GaiaAgent:
29
  def __init__(self, model_name="gpt-4o"):
30
  self.model_name = model_name
31
- self.client = openai.OpenAI() # Inizializza il client OpenAI qui
 
 
 
 
 
 
32
  print(f"GaiaAgent initialized with model: {self.model_name}")
33
- if not self.client.api_key: # Verifica se la chiave è stata caricata dal client
34
  print("WARNING: OpenAI API key not found by the client. Ensure OPENAI_API_KEY is set.")
35
 
 
36
  def _call_openai_api(self, messages, tools=None, tool_choice=None):
37
  try:
38
- response = self.client.chat.completions.create(
39
  model=self.model_name,
40
  messages=messages,
41
  tools=tools,
42
  tool_choice=tool_choice,
43
- temperature=0.1, # Bassa temperatura per risposte più deterministiche e fattuali
44
  )
45
  return response
46
  except openai.APIError as e:
47
  print(f"Errore API OpenAI: {e}")
48
- # Potresti voler restituire un messaggio di errore specifico o sollevare l'eccezione
49
  return f"Errore durante la chiamata all'API OpenAI: {str(e)}"
50
  except Exception as e:
51
  print(f"Errore imprevisto durante la chiamata OpenAI API: {e}")
@@ -53,24 +64,17 @@ class GaiaAgent:
53
 
54
 
55
  def _execute_python_code(self, code_string: str) -> str:
56
- """Esegue codice Python e restituisce l'output o un errore."""
57
  print(f"Esecuzione codice Python (primi 200 caratteri): {code_string[:200]}...")
58
  try:
59
- # Rimuovi i backtick e 'python' se presenti (comune nell'output LLM)
60
  code_string = re.sub(r"^```python\n", "", code_string)
61
  code_string = re.sub(r"\n```$", "", code_string)
62
  code_string = code_string.strip()
63
-
64
- # Prepara un ambiente per l'esecuzione del codice
65
- # Reindirizza stdout per catturare i print
66
  import io
67
  from contextlib import redirect_stdout
68
  f = io.StringIO()
69
  with redirect_stdout(f):
70
- exec(code_string, {}) # Usa un dizionario vuoto per globals per un minimo di isolamento
71
  s = f.getvalue()
72
-
73
- # Se non c'è output esplicito da print(), indica che l'esecuzione è avvenuta
74
  if not s:
75
  s = "Codice eseguito con successo, nessun output esplicito (print)."
76
  print(f"Esecuzione codice riuscita. Output (primi 200 caratteri): {s[:200]}")
@@ -82,7 +86,7 @@ class GaiaAgent:
82
  def _search_wikipedia(self, query: str) -> str:
83
  print(f"Ricerca Wikipedia per: {query}")
84
  try:
85
- wikipedia.set_lang("en") # Le domande GAIA sono in inglese
86
  results = wikipedia.search(query, results=MAX_WIKIPEDIA_RESULTS)
87
  if not results:
88
  return "Nessun risultato trovato su Wikipedia."
@@ -103,17 +107,33 @@ class GaiaAgent:
103
  except Exception as e:
104
  return f"Errore durante la ricerca su Wikipedia: {str(e)}"
105
 
106
- def _search_duckduckgo(self, query: str) -> str:
107
- print(f"Ricerca DuckDuckGo per: {query}")
 
 
108
  try:
109
- with DDGS() as ddgs:
110
- # Usare ddgs.text per risultati testuali, o ddgs.answers per risposte più dirette se disponibili
111
- results = list(ddgs.text(query, max_results=MAX_DDG_RESULTS))
112
- if not results:
113
- return "Nessun risultato trovato su DuckDuckGo."
114
- return "\n\n".join([f"Title: {r['title']}\nSnippet: {r['body'][:500]}...\nURL: {r['href']}" for r in results])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  except Exception as e:
116
- return f"Errore durante la ricerca su DuckDuckGo: {str(e)}"
117
 
118
  def _search_arxiv(self, query: str) -> str:
119
  print(f"Ricerca Arxiv per: {query}")
@@ -134,8 +154,11 @@ class GaiaAgent:
134
 
135
  def __call__(self, question: str) -> str:
136
  print(f"GaiaAgent ha ricevuto la domanda (primi 100 caratteri): {question[:100]}...")
137
- if not self.client.api_key:
138
  return "Errore: OPENAI_API_KEY non configurata o non valida per l'agente."
 
 
 
139
 
140
  tools = [
141
  {"type": "function", "function": {
@@ -143,27 +166,27 @@ class GaiaAgent:
143
  "description": "Cerca informazioni su Wikipedia. Utile per conoscenza generale, fatti, definizioni, storia.",
144
  "parameters": {"type": "object", "properties": {"query": {"type": "string", "description": "La query di ricerca per Wikipedia."}}, "required": ["query"]}}},
145
  {"type": "function", "function": {
146
- "name": "search_duckduckgo",
147
- "description": "Cerca sul web usando DuckDuckGo. Utile per eventi attuali, siti specifici, o quando Wikipedia non è sufficiente.",
148
- "parameters": {"type": "object", "properties": {"query": {"type": "string", "description": "La query di ricerca per DuckDuckGo."}}, "required": ["query"]}}},
149
  {"type": "function", "function": {
150
  "name": "search_arxiv",
151
  "description": "Cerca su Arxiv articoli scientifici e preprint (fisica, matematica, informatica, ecc.).",
152
  "parameters": {"type": "object", "properties": {"query": {"type": "string", "description": "La query di ricerca per Arxiv (es. autore, titolo, parole chiave)."}}, "required": ["query"]}}},
153
  {"type": "function", "function": {
154
  "name": "execute_python_code",
155
- "description": "Esegue una stringa di codice Python e restituisce il suo output. Usare per calcoli, manipolazione dati o qualsiasi task che richieda esecuzione di codice. Assicurarsi che il codice stampi il risultato su stdout. Il codice viene eseguito in un ambiente stateless. NON usare per installare pacchetti o interagire con file system.",
156
- "parameters": {"type": "object", "properties": {"code_string": {"type": "string", "description": "Il codice Python da eseguire. Deve essere uno script Python valido. Esempio: 'print(sum([i for i in range(101)]))'"}}, "required": ["code_string"]}}}
157
  ]
158
 
159
  system_prompt = (
160
  "Sei GaiaAgent, un assistente AI progettato per rispondere a domande in modo accurato e completo, specialmente per task complessi come quelli di GAIA. "
161
- "Hai accesso ai seguenti strumenti: ricerca Wikipedia, ricerca web DuckDuckGo, ricerca Arxiv e un interprete di codice Python. "
162
  "Segui questi passaggi per rispondere alla domanda dell'utente:\n"
163
  "1. **Analizza la Domanda**: Comprendi a fondo cosa viene chiesto. Se la domanda è complessa, scomponila in sotto-problemi.\n"
164
  "2. **Pianifica l'Uso degli Strumenti**: Decidi quali strumenti sono più appropriati e in quale ordine. Puoi usare più strumenti in sequenza.\n"
165
  " - `search_wikipedia`: per conoscenza generale consolidata.\n"
166
- " - `search_duckduckgo`: per informazioni recenti, argomenti di nicchia, o per confermare/trovare URL specifici.\n"
167
  " - `search_arxiv`: per ricerca scientifica e tecnica.\n"
168
  " - `execute_python_code`: per calcoli, elaborazione di dati testuali/numerici, o simulazioni. Il codice deve stampare esplicitamente i risultati.\n"
169
  "3. **Esegui e Itera**: Usa gli strumenti. Se uno strumento non fornisce l'informazione necessaria, valuta se riformulare la query, provare un altro strumento, o concludere che l'informazione non è reperibile con gli strumenti attuali.\n"
@@ -179,14 +202,14 @@ class GaiaAgent:
179
 
180
  api_response_or_error = self._call_openai_api(messages, tools=tools, tool_choice="auto")
181
 
182
- if isinstance(api_response_or_error, str): # Errore gestito da _call_openai_api
183
- return api_response_or_error # Restituisce il messaggio di errore
184
 
185
  response_message = api_response_or_error.choices[0].message
186
 
187
  if response_message.tool_calls:
188
  print(f"OpenAI suggerisce chiamate a strumenti: {[tc.function.name for tc in response_message.tool_calls]}")
189
- messages.append(response_message) # Aggiungi la risposta dell'assistente con le richieste di tool
190
 
191
  for tool_call in response_message.tool_calls:
192
  function_name = tool_call.function.name
@@ -196,14 +219,17 @@ class GaiaAgent:
196
  print(f"Errore nel decodificare gli argomenti JSON per {function_name}: {e}")
197
  tool_output = f"Errore: argomenti JSON invalidi per {function_name}."
198
  messages.append({"tool_call_id": tool_call.id, "role": "tool", "name": function_name, "content": tool_output})
199
- continue # Salta al prossimo tool_call o iterazione
200
 
201
  print(f"Esecuzione strumento: {function_name} con argomenti: {function_args}")
202
  tool_output = ""
203
  if function_name == "search_wikipedia":
204
  tool_output = self._search_wikipedia(query=function_args.get("query",""))
205
- elif function_name == "search_duckduckgo":
206
- tool_output = self._search_duckduckgo(query=function_args.get("query",""))
 
 
 
207
  elif function_name == "search_arxiv":
208
  tool_output = self._search_arxiv(query=function_args.get("query",""))
209
  elif function_name == "execute_python_code":
@@ -214,26 +240,24 @@ class GaiaAgent:
214
  print(f"Output strumento {function_name} (primi 100 caratteri): {str(tool_output)[:100]}")
215
  messages.append({"tool_call_id": tool_call.id, "role": "tool", "name": function_name, "content": str(tool_output)})
216
 
217
- else: # Nessuna chiamata a strumento, l'LLM dovrebbe aver fornito una risposta finale
218
  final_answer = response_message.content
219
  if final_answer:
220
  print(f"Agente restituisce risposta finale (primi 200 caratteri): {final_answer[:200]}")
221
  return final_answer
222
- else: # Risposta vuota, prova a forzare una risposta basata sulla cronologia
223
  print("L'LLM non ha chiamato strumenti e non ha fornito contenuto. Tento di forzare una risposta.")
224
  messages.append({"role": "user", "content": "Per favore, fornisci la migliore risposta possibile basata sulle informazioni raccolte finora, senza usare altri strumenti."})
225
- final_attempt_response = self._call_openai_api(messages) # No tools this time
226
- if isinstance(final_attempt_response, str): return final_attempt_response # Errore
227
  if final_attempt_response and final_attempt_response.choices[0].message.content:
228
  return final_attempt_response.choices[0].message.content
229
  return "L'agente ha ricevuto una risposta finale vuota e non è riuscito a generarne una alternativa."
230
 
231
-
232
  print("L'agente ha raggiunto il numero massimo di iterazioni degli strumenti.")
233
- # Tenta un'ultima chiamata per sintetizzare
234
  messages.append({"role": "user", "content": "Hai raggiunto il limite di utilizzo degli strumenti. Per favore, fornisci la migliore risposta possibile basata sulle informazioni raccolte finora."})
235
- final_summary_response = self._call_openai_api(messages) # No tools
236
- if isinstance(final_summary_response, str): return final_summary_response # Errore
237
  if final_summary_response and final_summary_response.choices[0].message.content:
238
  return final_summary_response.choices[0].message.content
239
  return "L'agente ha raggiunto il numero massimo di iterazioni e non è riuscito a formulare una risposta finale."
 
1
  import os
2
  import openai
3
  import wikipedia
4
+ from tavily import TavilyClient # Importa TavilyClient
5
  import arxiv
6
  import json
7
  import re
8
 
9
+ # Carica le chiavi API dalle variabili d'ambiente
10
  # Per i test locali, puoi usare python-dotenv e un file .env
11
  # from dotenv import load_dotenv
12
  # load_dotenv()
 
13
 
14
+ # La libreria OpenAI >1.0.0 gestisce automaticamente OPENAI_API_KEY
15
+ # La chiave Tavily deve essere caricata esplicitamente o passata al client
16
+
17
+ TAVILY_API_KEY = os.getenv("TAVILY_API_KEY")
18
+
19
  if not os.getenv("OPENAI_API_KEY"):
20
  print("ATTENZIONE: La variabile d'ambiente OPENAI_API_KEY non è impostata.")
21
  print("L'agente potrebbe non funzionare correttamente senza una chiave API OpenAI valida.")
22
 
23
+ if not TAVILY_API_KEY:
24
+ print("ATTENZIONE: La variabile d'ambiente TAVILY_API_KEY non è impostata.")
25
+ print("La ricerca Tavily non funzionerà senza una chiave API valida.")
26
+
27
 
28
  MAX_WIKIPEDIA_RESULTS = 3
29
+ MAX_TAVILY_RESULTS = 5 # Tavily può restituire risultati più ricchi
30
  MAX_ARXIV_RESULTS = 3
31
+ MAX_TOOL_ITERATIONS = 7
32
 
33
  class GaiaAgent:
34
  def __init__(self, model_name="gpt-4o"):
35
  self.model_name = model_name
36
+ self.openai_client = openai.OpenAI() # Inizializza il client OpenAI
37
+ if TAVILY_API_KEY:
38
+ self.tavily_client = TavilyClient(api_key=TAVILY_API_KEY)
39
+ else:
40
+ self.tavily_client = None
41
+ print("Cliente Tavily non inizializzato a causa della mancanza di TAVILY_API_KEY.")
42
+
43
  print(f"GaiaAgent initialized with model: {self.model_name}")
44
+ if not self.openai_client.api_key:
45
  print("WARNING: OpenAI API key not found by the client. Ensure OPENAI_API_KEY is set.")
46
 
47
+
48
  def _call_openai_api(self, messages, tools=None, tool_choice=None):
49
  try:
50
+ response = self.openai_client.chat.completions.create(
51
  model=self.model_name,
52
  messages=messages,
53
  tools=tools,
54
  tool_choice=tool_choice,
55
+ temperature=0.1,
56
  )
57
  return response
58
  except openai.APIError as e:
59
  print(f"Errore API OpenAI: {e}")
 
60
  return f"Errore durante la chiamata all'API OpenAI: {str(e)}"
61
  except Exception as e:
62
  print(f"Errore imprevisto durante la chiamata OpenAI API: {e}")
 
64
 
65
 
66
  def _execute_python_code(self, code_string: str) -> str:
 
67
  print(f"Esecuzione codice Python (primi 200 caratteri): {code_string[:200]}...")
68
  try:
 
69
  code_string = re.sub(r"^```python\n", "", code_string)
70
  code_string = re.sub(r"\n```$", "", code_string)
71
  code_string = code_string.strip()
 
 
 
72
  import io
73
  from contextlib import redirect_stdout
74
  f = io.StringIO()
75
  with redirect_stdout(f):
76
+ exec(code_string, {})
77
  s = f.getvalue()
 
 
78
  if not s:
79
  s = "Codice eseguito con successo, nessun output esplicito (print)."
80
  print(f"Esecuzione codice riuscita. Output (primi 200 caratteri): {s[:200]}")
 
86
  def _search_wikipedia(self, query: str) -> str:
87
  print(f"Ricerca Wikipedia per: {query}")
88
  try:
89
+ wikipedia.set_lang("en")
90
  results = wikipedia.search(query, results=MAX_WIKIPEDIA_RESULTS)
91
  if not results:
92
  return "Nessun risultato trovato su Wikipedia."
 
107
  except Exception as e:
108
  return f"Errore durante la ricerca su Wikipedia: {str(e)}"
109
 
110
+ def _search_tavily(self, query: str) -> str:
111
+ print(f"Ricerca Tavily per: {query}")
112
+ if not self.tavily_client:
113
+ return "Errore: Tavily API key non configurata. Impossibile eseguire la ricerca."
114
  try:
115
+ # Puoi personalizzare i parametri di ricerca di Tavily qui
116
+ # ad esempio: search_depth="advanced", include_answer=True, include_raw_content=False
117
+ response = self.tavily_client.search(
118
+ query=query,
119
+ search_depth="basic", # "basic" per velocità, "advanced" per risposte più approfondite
120
+ max_results=MAX_TAVILY_RESULTS,
121
+ include_answer=True # Chiede a Tavily di provare a fornire una risposta diretta
122
+ )
123
+
124
+ results_str = ""
125
+ if response.get("answer"):
126
+ results_str += f"Risposta diretta da Tavily: {response['answer']}\n\n"
127
+
128
+ if response.get("results"):
129
+ results_str += "Risultati della ricerca:\n"
130
+ for r in response["results"]:
131
+ results_str += f"Title: {r.get('title', 'N/A')}\nURL: {r.get('url', 'N/A')}\nContent Snippet: {r.get('content', 'N/A')[:500]}...\n\n"
132
+
133
+ return results_str if results_str else "Nessun risultato significativo trovato da Tavily."
134
+
135
  except Exception as e:
136
+ return f"Errore durante la ricerca su Tavily: {str(e)}"
137
 
138
  def _search_arxiv(self, query: str) -> str:
139
  print(f"Ricerca Arxiv per: {query}")
 
154
 
155
  def __call__(self, question: str) -> str:
156
  print(f"GaiaAgent ha ricevuto la domanda (primi 100 caratteri): {question[:100]}...")
157
+ if not self.openai_client.api_key:
158
  return "Errore: OPENAI_API_KEY non configurata o non valida per l'agente."
159
+ if not self.tavily_client:
160
+ print("Avviso: Tavily client non inizializzato. La ricerca web non sarà disponibile.")
161
+
162
 
163
  tools = [
164
  {"type": "function", "function": {
 
166
  "description": "Cerca informazioni su Wikipedia. Utile per conoscenza generale, fatti, definizioni, storia.",
167
  "parameters": {"type": "object", "properties": {"query": {"type": "string", "description": "La query di ricerca per Wikipedia."}}, "required": ["query"]}}},
168
  {"type": "function", "function": {
169
+ "name": "search_tavily", # Nome dello strumento aggiornato
170
+ "description": "Cerca sul web usando l'API di Tavily. Utile per eventi attuali, informazioni specifiche, siti web, o quando Wikipedia non è sufficiente. Può fornire risposte dirette e snippet di contenuto.",
171
+ "parameters": {"type": "object", "properties": {"query": {"type": "string", "description": "La query di ricerca per Tavily."}}, "required": ["query"]}}},
172
  {"type": "function", "function": {
173
  "name": "search_arxiv",
174
  "description": "Cerca su Arxiv articoli scientifici e preprint (fisica, matematica, informatica, ecc.).",
175
  "parameters": {"type": "object", "properties": {"query": {"type": "string", "description": "La query di ricerca per Arxiv (es. autore, titolo, parole chiave)."}}, "required": ["query"]}}},
176
  {"type": "function", "function": {
177
  "name": "execute_python_code",
178
+ "description": "Esegue una stringa di codice Python e restituisce il suo output. Usare per calcoli, manipolazione dati o qualsiasi task che richieda esecuzione di codice. Assicurarsi che il codice stampi il risultato su stdout. Il codice viene eseguito in un ambiente stateless.",
179
+ "parameters": {"type": "object", "properties": {"code_string": {"type": "string", "description": "Il codice Python da eseguire. Esempio: 'print(1+1)'"}}, "required": ["code_string"]}}}
180
  ]
181
 
182
  system_prompt = (
183
  "Sei GaiaAgent, un assistente AI progettato per rispondere a domande in modo accurato e completo, specialmente per task complessi come quelli di GAIA. "
184
+ "Hai accesso ai seguenti strumenti: ricerca Wikipedia, ricerca web Tavily, ricerca Arxiv e un interprete di codice Python. " # Aggiornato DuckDuckGo a Tavily
185
  "Segui questi passaggi per rispondere alla domanda dell'utente:\n"
186
  "1. **Analizza la Domanda**: Comprendi a fondo cosa viene chiesto. Se la domanda è complessa, scomponila in sotto-problemi.\n"
187
  "2. **Pianifica l'Uso degli Strumenti**: Decidi quali strumenti sono più appropriati e in quale ordine. Puoi usare più strumenti in sequenza.\n"
188
  " - `search_wikipedia`: per conoscenza generale consolidata.\n"
189
+ " - `search_tavily`: per informazioni recenti, argomenti di nicchia, o per confermare/trovare URL specifici. Può fornire risposte dirette.\n" # Aggiornato
190
  " - `search_arxiv`: per ricerca scientifica e tecnica.\n"
191
  " - `execute_python_code`: per calcoli, elaborazione di dati testuali/numerici, o simulazioni. Il codice deve stampare esplicitamente i risultati.\n"
192
  "3. **Esegui e Itera**: Usa gli strumenti. Se uno strumento non fornisce l'informazione necessaria, valuta se riformulare la query, provare un altro strumento, o concludere che l'informazione non è reperibile con gli strumenti attuali.\n"
 
202
 
203
  api_response_or_error = self._call_openai_api(messages, tools=tools, tool_choice="auto")
204
 
205
+ if isinstance(api_response_or_error, str):
206
+ return api_response_or_error
207
 
208
  response_message = api_response_or_error.choices[0].message
209
 
210
  if response_message.tool_calls:
211
  print(f"OpenAI suggerisce chiamate a strumenti: {[tc.function.name for tc in response_message.tool_calls]}")
212
+ messages.append(response_message)
213
 
214
  for tool_call in response_message.tool_calls:
215
  function_name = tool_call.function.name
 
219
  print(f"Errore nel decodificare gli argomenti JSON per {function_name}: {e}")
220
  tool_output = f"Errore: argomenti JSON invalidi per {function_name}."
221
  messages.append({"tool_call_id": tool_call.id, "role": "tool", "name": function_name, "content": tool_output})
222
+ continue
223
 
224
  print(f"Esecuzione strumento: {function_name} con argomenti: {function_args}")
225
  tool_output = ""
226
  if function_name == "search_wikipedia":
227
  tool_output = self._search_wikipedia(query=function_args.get("query",""))
228
+ elif function_name == "search_tavily": # Aggiornato per chiamare Tavily
229
+ if not self.tavily_client:
230
+ tool_output = "Errore: Tavily client non inizializzato. Impossibile eseguire la ricerca Tavily."
231
+ else:
232
+ tool_output = self._search_tavily(query=function_args.get("query",""))
233
  elif function_name == "search_arxiv":
234
  tool_output = self._search_arxiv(query=function_args.get("query",""))
235
  elif function_name == "execute_python_code":
 
240
  print(f"Output strumento {function_name} (primi 100 caratteri): {str(tool_output)[:100]}")
241
  messages.append({"tool_call_id": tool_call.id, "role": "tool", "name": function_name, "content": str(tool_output)})
242
 
243
+ else:
244
  final_answer = response_message.content
245
  if final_answer:
246
  print(f"Agente restituisce risposta finale (primi 200 caratteri): {final_answer[:200]}")
247
  return final_answer
248
+ else:
249
  print("L'LLM non ha chiamato strumenti e non ha fornito contenuto. Tento di forzare una risposta.")
250
  messages.append({"role": "user", "content": "Per favore, fornisci la migliore risposta possibile basata sulle informazioni raccolte finora, senza usare altri strumenti."})
251
+ final_attempt_response = self._call_openai_api(messages)
252
+ if isinstance(final_attempt_response, str): return final_attempt_response
253
  if final_attempt_response and final_attempt_response.choices[0].message.content:
254
  return final_attempt_response.choices[0].message.content
255
  return "L'agente ha ricevuto una risposta finale vuota e non è riuscito a generarne una alternativa."
256
 
 
257
  print("L'agente ha raggiunto il numero massimo di iterazioni degli strumenti.")
 
258
  messages.append({"role": "user", "content": "Hai raggiunto il limite di utilizzo degli strumenti. Per favore, fornisci la migliore risposta possibile basata sulle informazioni raccolte finora."})
259
+ final_summary_response = self._call_openai_api(messages)
260
+ if isinstance(final_summary_response, str): return final_summary_response
261
  if final_summary_response and final_summary_response.choices[0].message.content:
262
  return final_summary_response.choices[0].message.content
263
  return "L'agente ha raggiunto il numero massimo di iterazioni e non è riuscito a formulare una risposta finale."