TL;DR
In questo articolo esploriamo come creare un agente di intelligenza artificiale conversazionale utilizzando i dati sui cambiamenti climatici provenienti da fonti eccellenti Futuri probabili API e la nuova API OpenAI Assistants. L’agente AI è in grado di rispondere a domande su come il clima potrebbe influenzare una posizione specifica e anche di eseguire analisi di dati di base. Gli assistenti IA possono essere adatti a compiti come questo, fornendo un canale promettente per presentare dati complessi a utenti non tecnici.
Recentemente stavo chiacchierando con un vicino su come i cambiamenti climatici potrebbero influenzarci e su come preparare al meglio le case per eventi meteorologici estremi. Ci sono alcuni siti web fantastici che forniscono informazioni relative a questo sotto forma di mappa, ma mi chiedevo se a volte le persone potrebbero semplicemente voler porre domande del tipo “In che modo la mia casa sarà influenzata dai cambiamenti climatici?” E “Cosa posso fare al riguardo?” e ottieni un riepilogo conciso con suggerimenti su come prepararsi. Ho quindi deciso di esplorare alcuni degli strumenti di intelligenza artificiale resi disponibili nelle ultime settimane.
Agenti IA alimentati da modelli linguistici di grandi dimensioni come GPT-4 stanno emergendo come un modo per consentire alle persone di interagire con documenti e dati attraverso la conversazione. Questi agenti interpretano ciò che la persona chiede, chiamano API e database per ottenere dati, generano ed eseguono codice per eseguire analisi, prima di presentare i risultati all’utente. Quadri brillanti come langchain E autogeno stanno aprendo la strada, fornendo modelli per implementare facilmente gli agenti. Di recente, OpenAI si è unita alla festa con il lancio di GPT come un modo senza codice per creare agenti, che ho esplorato Questo articolo. Questi sono progettati molto bene e aprono la strada a un pubblico molto più ampio, ma presentano alcune limitazioni. Richiedono un’API con una specifica openapi.json, il che significa che attualmente non supportano standard come graphql. Inoltre, non supportano la possibilità di registrare funzioni, cosa prevedibile per una soluzione senza codice, ma che può limitarne le capacità.
Inserisci l’altro lancio recente di OpenAI: API degli assistenti.
L’API Assistants (in versione beta) è un modo programmatico per configurare OpenAI Assistants che supporta funzioni, navigazione Web e recupero di conoscenze dai documenti caricati. Le funzioni rappresentano una grande differenza rispetto ai GPT, poiché consentono un’interazione più complessa con fonti di dati esterne. Le funzioni sono i luoghi in cui i Large Language Models (LLM) come GPT-4 vengono informati del fatto che alcuni input dell’utente dovrebbero comportare una chiamata a una funzione di codice. LLM genererà una risposta in formato JSON con gli esatti parametri necessari per chiamare la funzione, che potrà quindi essere utilizzata per l’esecuzione locale. Per vedere come funzionano in dettaglio con OpenAI, vedere Qui.
Per poter creare un agente AI che ci aiuti nella preparazione al cambiamento climatico, abbiamo bisogno di una buona fonte di dati sul cambiamento climatico e di un’API per estrarre tali informazioni. Qualsiasi risorsa di questo tipo deve applicare un approccio rigoroso per combinare le previsioni del Modello di Circolazione Generale (GCM).
Fortunatamente, la gente di Futuri probabili hanno fatto un lavoro fantastico!
Il futuro probabile è “Un’iniziativa no-profit di alfabetizzazione climatica che rende strumenti pratici, storie e risorse disponibili online a tutti, ovunque.”, e forniscono una serie di mappe e dati basati sul quadro CORDEX-CORE, una standardizzazione per i modelli climatici regionali REMO2015 e REGCM4. (Nota a margine: non sono affiliato con Probable Futures)
È importante sottolineare che forniscono a API GraphQL per accedere a questi dati a cui avrei potuto accedere dopo richiedendo una chiave API.
Basato su la documentazione Ho creato funzioni che ho salvato in un file assistant_tools.py
…
pf_api_url = "https://graphql.probablefutures.org"
pf_token_audience = "https://graphql.probablefutures.com"
pf_token_url = "https://probablefutures.us.auth0.com/oauth/token"def get_pf_token():
client_id = os.getenv("CLIENT_ID")
client_secret = os.getenv("CLIENT_SECRET")
response = requests.post(
pf_token_url,
json={
"client_id": client_id,
"client_secret": client_secret,
"audience": pf_token_audience,
"grant_type": "client_credentials",
},
)
access_token = response.json()("access_token")
return access_token
def get_pf_data(address, country, warming_scenario="1.5"):
variables = {}
location = f"""
country: "{country}"
address: "{address}"
"""
query = (
"""
mutation {
getDatasetStatistics(input: { """
+ location
+ """ \
warmingScenario: \"""" + warming_scenario + """\"
}) {
datasetStatisticsResponses{
datasetId
midValue
name
unit
warmingScenario
latitude
longitude
info
}
}
}
"""
)
print(query)
access_token = get_pf_token()
url = pf_api_url + "/graphql"
headers = {"Authorization": "Bearer " + access_token}
response = requests.post(
url, json={"query": query, "variables": variables}, headers=headers
)
return str(response.json())
Ho intenzionalmente escluso datasetId
al fine di recuperare tutti gli indicatori in modo che l’agente AI abbia un’ampia gamma di informazioni con cui lavorare.
L’API è solida in quanto accetta paesi e città, nonché indirizzi completi. Per esempio …
get_pf_data(address="New Delhi", country="India", warming_scenario="1.5")
Restituisce un record JSON con informazioni sul cambiamento climatico per la posizione…
{'data': {'getDatasetStatistics': {'datasetStatisticsResponses': ({'datasetId': 40601, 'midValue': '17.0', 'name': 'Change in total annual precipitation', 'unit': 'mm', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40616, 'midValue': '14.0', 'name': 'Change in wettest 90 days', 'unit': 'mm', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40607, 'midValue': '19.0', 'name': 'Change in dry hot days', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40614, 'midValue': '0.0', 'name': 'Change in snowy days', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40612, 'midValue': '2.0', 'name': 'Change in frequency of “1-in-100-year” storm', 'unit': 'x as frequent', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40101, 'midValue': '28.0', 'name': 'Average temperature', 'unit': '°C', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40901, 'midValue': '4.0', 'name': 'Climate zones', 'unit': 'class', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {'climateZoneName': 'Dry semi-arid (or steppe) hot'}}, {'datasetId': 40613, 'midValue': '49.0', 'name': 'Change in precipitation “1-in-100-year” storm', 'unit': 'mm', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40701, 'midValue': '7.0', 'name': 'Likelihood of year-plus extreme drought', 'unit': '%', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40702, 'midValue': '30.0', 'name': 'Likelihood of year-plus drought', 'unit': '%', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40704, 'midValue': '5.0', 'name': 'Change in wildfire danger days', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40703, 'midValue': '-0.2', 'name': 'Change in water balance', 'unit': 'z-score', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40201, 'midValue': '21.0', 'name': 'Average nighttime temperature', 'unit': '°C', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40205, 'midValue': '0.0', 'name': 'Freezing days', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40301, 'midValue': '71.0', 'name': 'Days above 26°C (78°F) wet-bulb', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40302, 'midValue': '24.0', 'name': 'Days above 28°C (82°F) wet-bulb', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40303, 'midValue': '2.0', 'name': 'Days above 30°C (86°F) wet-bulb', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40102, 'midValue': '35.0', 'name': 'Average daytime temperature', 'unit': '°C', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40103, 'midValue': '49.0', 'name': '10 hottest days', 'unit': '°C', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40104, 'midValue': '228.0', 'name': 'Days above 32°C (90°F)', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40105, 'midValue': '187.0', 'name': 'Days above 35°C (95°F)', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40106, 'midValue': '145.0', 'name': 'Days above 38°C (100°F)', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40202, 'midValue': '0.0', 'name': 'Frost nights', 'unit': 'nights', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40304, 'midValue': '0.0', 'name': 'Days above 32°C (90°F) wet-bulb', 'unit': 'days', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40305, 'midValue': '29.0', 'name': '10 hottest wet-bulb days', 'unit': '°C', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40203, 'midValue': '207.0', 'name': 'Nights above 20°C (68°F)', 'unit': 'nights', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}}, {'datasetId': 40204, 'midValue': '147.0', 'name': 'Nights above 25°C (77°F)', 'unit': 'nights', 'warmingScenario': '1.5', 'latitude': 28.6, 'longitude': 77.2, 'info': {}})}}}
Successivamente, dobbiamo creare l’assistente AI utilizzando l’API beta. Ci sono alcune buone risorse dentro la documentazione e anche molto utile Libro di cucina OpenAI. Tuttavia, essendo così nuovo e in versione beta, non esiste Quello c’erano ancora molte informazioni in giro, quindi a volte è stato un po’ di tentativi ed errori.
Innanzitutto, dobbiamo configurare gli strumenti che l’assistente può utilizzare, come la funzione per ottenere dati sui cambiamenti climatici. Seguente la documentazione …
get_pf_data_schema = {
"name": "get_pf_data",
"parameters": {
"type": "object",
"properties": {
"address": {
"type": "string",
"description": ("The address of the location to get data for"),
},
"country": {
"type": "string",
"description": ("The country of location to get data for"),
},
"warming_scenario": {
"type": "string",
"enum": ("1.0", "1.5", "2.0", "2.5", "3.0"),
"description": ("The warming scenario to get data for. Default is 1.5"),
}},
"required": ("address", "country"),
},
"description": """
This is the API call to the probable futures API to get predicted climate change indicators for a location
""",
}
Noterai che abbiamo fornito descrizioni di testo per ciascun parametro nella funzione. Dalla sperimentazione, questo sembra essere utilizzato dall’agente durante il popolamento dei parametri, quindi fai attenzione a essere il più chiaro possibile e a prendere nota di eventuali idiosincrasie in modo che LLM possa adattarsi. Da questo definiamo gli strumenti…
tools = (
{
"type": "function",
"function": get_pf_data_schema,
}
{"type": "code_interpreter"},
)
Noterai che ho lasciato code_interpretor, dando all’assistente la possibilità di eseguire il codice necessario per l’analisi dei dati.
Successivamente, dobbiamo specificare una serie di istruzioni per l’utente (un prompt di sistema). Questi sono assolutamente fondamentali per adattare le prestazioni degli assistenti al nostro compito. Sulla base di alcune rapide sperimentazioni sono arrivato a questo set…
instructions = """
"Hello, Climate Change Assistant. You help people understand how climate change will affect their homes"
"You will use Probable Futures Data to predict climate change indicators for a location"
"You will summarize perfectly the returned data"
"You will also provide links to local resources and websites to help the user prepare for the predicted climate change"
"If you don't have enough address information, request it"
"You default to warming scenario of 1.5 if not specified, but ask if the user wants to try others after presenting results"
"Group results into categories"
"Always link to the probable futures website for the location using URL and replacing LATITUDE and LONGITUDE with location values: https://probablefutures.org/maps/?selected_map=days_above_32c&map_version=latest&volume=heat&warming_scenario=1.5&map_projection=mercator#9.2/LATITUDE/LONGITUDE"
"GENERATE OUTPUT THAT IS CLEAR AND EASY TO UNDERSTAND FOR A NON-TECHNICAL USER"
"""
Puoi vedere che ho aggiunto istruzioni affinché l’assistente fornisca risorse come siti Web per aiutare gli utenti a prepararsi al cambiamento climatico. Questo è un po’ “aperto”, per un assistente di produzione probabilmente vorremmo una cura più rigorosa di questo aspetto.
Una cosa meravigliosa che ora è possibile è che possiamo anche dare istruzioni riguardo al tono generale, nel caso precedente richiedendo che l’output sia chiaro a un utente non tecnico. Ovviamente, tutto ciò richiede una tempestiva ingegneria sistematica, ma è interessante notare come ora “programmiamo” in parte attraverso la persuasione. 😊
OK, ora abbiamo i nostri strumenti e le istruzioni, creiamo l’assistente…
import os
from openai import AsyncOpenAI
import asyncio
from dotenv import load_dotenv
import sysload_dotenv()
api_key = os.environ.get("OPENAI_API_KEY")
assistant_id = os.environ.get("ASSISTANT_ID")
model = os.environ.get("MODEL")
client = AsyncOpenAI(api_key=api_key)
name = "Climate Change Assistant"
try:
my_assistant = await client.beta.assistants.retrieve(assistant_id)
print("Updating existing assistant ...")
assistant = await client.beta.assistants.update(
assistant_id,
name=name,
instructions=instructions,
tools=tools,
model=model,
)
except:
print("Creating assistant ...")
assistant = await client.beta.assistants.create(
name=name,
instructions=instructions,
tools=tools,
model=model,
)
print(assistant)
print("Now save the DI in your .env file")
Quanto sopra presuppone che abbiamo definito le chiavi e il nostro ID agente in a .env
file. Noterai che il codice controlla innanzitutto se l’agente esiste utilizzando il file ASSISTANT_ID
nel .env
file e aggiornalo in tal caso, altrimenti crea un nuovo agente e l’ID generato deve essere copiato nel file .env
file. Senza questo, stavo creando MOLTI assistenti!
Una volta creato l’assistente, diventa visibile sul file Interfaccia utente OpenAI dove può essere testato nel Terreno di gioco. Poiché la maggior parte dello sviluppo e del debugging riguardavano chiamate di funzioni che in realtà chiamavano codice, non ho trovato il parco giochi molto utile per questa analisi, ma è progettato bene e potrebbe essere utile in altri lavori.
Per questa analisi, ho deciso di utilizzare il nuovo GPT-4-Turbo modello in base all’impostazione model
a “gpt-4–1106-anteprima”.
Vogliamo essere in grado di creare un chatbot completo, quindi ho iniziato con questo esempio di libro di cucina illuminato a catenamodificandolo leggermente per separare il codice agente in un file dedicato e per accedervi tramite…
import assistant_tools as at
Chainlit è molto conciso e l’interfaccia utente è facile da configurare, puoi trovare il codice per l’app Qui.
Mettendo tutto insieme: vedere il codice Qui – avviamo l’agente con un semplice chainlit run app.py
…
Chiediamo una posizione…
Notando sopra che ho intenzionalmente scritto male Mombasa.
L’agente inizia quindi il suo lavoro, chiamando l’API ed elaborando la risposta JSON (ci sono voluti circa 20 secondi)…
Sulla base delle nostre istruzioni, si conclude poi con…
Ma è giusto?
Chiamiamo l’API ed esaminiamo l’output…
get_pf_data(address="Mombassa", country="Kenya", warming_scenario="1.5")
Che interroga l’API con…
mutation {
getDatasetStatistics(input: {
country: "Kenya"
address: "Mombassa"
warmingScenario: "1.5"
}) {
datasetStatisticsResponses{
datasetId
midValue
name
unit
warmingScenario
latitude
longitude
info
}
}
}
Ciò fornisce quanto segue (troncato per visualizzarne solo alcuni)…
{
"data": {
"getDatasetStatistics": {
"datasetStatisticsResponses": (
{
"datasetId": 40601,
"midValue": "30.0",
"name": "Change in total annual precipitation",
"unit": "mm",
"warmingScenario": "1.5",
"latitude": -4,
"longitude": 39.6,
"info": {}
},
{
"datasetId": 40616,
"midValue": "70.0",
"name": "Change in wettest 90 days",
"unit": "mm",
"warmingScenario": "1.5",
"latitude": -4,
"longitude": 39.6,
"info": {}
},
{
"datasetId": 40607,
"midValue": "21.0",
"name": "Change in dry hot days",
"unit": "days",
"warmingScenario": "1.5",
"latitude": -4,
"longitude": 39.6,
"info": {}
},
{
"datasetId": 40614,
"midValue": "0.0",
"name": "Change in snowy days",
"unit": "days",
"warmingScenario": "1.5",
"latitude": -4,
"longitude": 39.6,
"info": {}
},
{
"datasetId": 40612,
"midValue": "1.0",
"name": "Change in frequency of \u201c1-in-100-year\u201d storm",
"unit": "x as frequent",
"warmingScenario": "1.5",
"latitude": -4,
"longitude": 39.6,
"info": {}
},.... etc
}
)
}
}
}
Da un controllo a campione sembra che l’agente li abbia catturati perfettamente e presentato all’utente un riepilogo accurato.
L’agente AI può essere migliorato attraverso alcune istruzioni su come presenta le informazioni.
Una delle istruzioni era quella di generare sempre un collegamento alla visualizzazione della mappa sul sito web di Probable Futures, che quando cliccato va nella posizione giusta…
Un’altra istruzione chiedeva all’agente di chiedere sempre all’utente di provare altri scenari di riscaldamento. Per impostazione predefinita, l’agente produce risultati per un aumento globale previsto della temperatura di 1,5°C, ma consentiamo all’utente di esplorare altri scenari, alquanto deprimenti.
Poiché abbiamo fornito all’agente AI l’abilità di interprete del codice, dovrebbe essere in grado di eseguire codice Python per eseguire analisi di base dei dati. Proviamolo.
Per prima cosa ho chiesto in che modo il cambiamento climatico avrebbe influenzato Londra e New York, a cui l’agente ha fornito dei riassunti. Poi ho chiesto…
Ciò ha portato l’agente a utilizzare l’interprete di codice per generare ed eseguire codice Python per creare una trama…
Non male!
Utilizzando l’API Probable Futures e un assistente OpenAI siamo stati in grado di creare un’interfaccia conversazionale che mostra come le persone potrebbero essere in grado di porre domande sul cambiamento climatico e ottenere consigli su come prepararsi. L’agente è stato in grado di effettuare chiamate API e di eseguire alcune analisi di base dei dati. Ciò offre un altro canale per la consapevolezza climatica, che potrebbe essere più attraente per alcuni utenti non tecnici.
Ovviamente avremmo potuto sviluppare un chatbot per determinare intenti/entità e codice per gestire l’API, ma questo richiede più lavoro e dovrebbe essere rivisitato per eventuali modifiche all’API e quando vengono aggiunte nuove API. Inoltre, un Large Language Model Agent svolge un buon lavoro interpretando l’input e il riepilogo dell’utente con uno sviluppo molto limitato e porta le cose a un altro livello essendo in grado di eseguire codice ed eseguire analisi di dati di base. Il nostro particolare caso d’uso sembra particolarmente adatto a un agente AI perché l’attività ha una portata limitata.
Ci sono però alcune sfide, la tecnica è un po’ lenta (il completamento delle query richiede circa 20-30 secondi). Inoltre, i costi dei token LLM non sono stati analizzati per questo articolo e potrebbero essere proibitivi.
Detto questo, l’API OpenAI Assistants è in versione beta. Inoltre l’agente non è stato messo a punto in alcun modo e quindi, con ulteriore lavoro, funzioni extra per attività comuni, prestazioni e costi potrebbero probabilmente essere ottimizzate per questa nuova entusiasmante tecnica.
Questo articolo si basa su dati e altri contenuti resi disponibili da Probable Futures, un progetto della SouthCoast Community Foundation e alcuni di tali dati potrebbero essere stati forniti a Probable Futures da Woodwell Climate Research Center, Inc. o The Coordinated Regional Climate Downscaling Experiment (CORDEX )
È possibile trovare il codice per questa analisi Qui.
Puoi trovare altri miei articoli Qui.
Fonte: towardsdatascience.com