Studiare un chatbot di report sulla situazione di un disastro umanitario – Utilizzando GPT-4-Turbo e il prompting a contesto completo

Analisi di un chatbot sull'andamento di una situazione di emergenza umanitaria - Sfruttando GPT-4-Turbo e il prompting a contesto completo

TLDR

In questo articolo esploreremo il nuovissimo modello GPT-4-Turbo di OpenAI, utilizzando la sua finestra di contesto aumentata a 128k token per passare un intero corpus di documenti per il recupero delle informazioni. Questo metodo grezzo e forzuto, possibile solo con finestre di contesto più ampie, è semplice da implementare e non richiede incorporamenti di documenti e ricerca semantica come quelli utilizzati in Retrieval Augmented Generation (RAG). Applicato a rapporti sulle situazioni di emergenza umanitaria pubblicati sulla fantastica piattaforma ReliefWeb – compressi utilizzando le Rappresentazioni Sparse di Priming (SPR) – dimostriamo che GPT-4-Turbo è in grado di rispondere a domande di base su recenti disastri. Tuttavia, anche con la recente diminuzione dei costi dei token di OpenAI, questo approccio è proibitivamente costoso e il modello di anteprima GPT-4-Turbo richiede molto tempo, talvolta impiegando fino a un minuto per rispondere. Come per tutti i modelli di recupero delle informazioni di LLM, è ovviamente cruciale implementare un framework di convalida per garantire che allucinazioni ed omissioni di informazioni siano controllate. Detto questo, GPT-4-Turbo rappresenta un grande passo avanti in termini di capacità, specialmente nel momento in cui migliora le prestazioni e i costi diminuiscono, aggiungendosi alla rapidamente espandente attrezzatura di LLM.

Il nuovo GPT-4-Turbo ha una finestra di contesto più ampia di 128k token. Immagine generata da GPT-4 + Dall-E-3.

Dato il ritmo frenetico degli sviluppi negli ultimi mesi con il rilascio di autogen, memgpt, Semantic Kernal e GPT e GPT-4-Turbo di OpenAI, ho pensato di scrivere una serie di articoli che confrontano alcune delle tecniche offerte da questi nuovi strumenti per il recupero delle informazioni conversazionali. Ognuno ha i suoi vantaggi e svantaggi, e alcuni rappresentano un potenziale cambiamento di paradigma nell’utilizzo dei Large Language Models (LLM). È un periodo incredibile, ma l’utilizzo di queste nuove tecniche nelle applicazioni del mondo reale non è sempre facile come sembra inizialmente.

OpenAI rilascia GPT-4-Turbo (Anteprima)

Il recente annuncio di OpenAI al DevDay ha incluso alcune nuove funzionalità che potrebbero cambiare il panorama dell’AI generativa. Una di queste è il rilascio (in anteprima) di GPT-4-Turbo con un limite aumentato di finestra di contesto (prompt) di 128k token, rispetto ai 32k precedenti. In precedenza, Claude AI offriva il limite di contesto commerciale più ampio di 100k token, quindi GPT-4-Turbo è un passo oltre questo. Inoltre, OpenAI sostiene che il loro nuovo modello è più competente nel seguire le istruzioni e sarà 3 volte più economico di GPT-4. Essendo il leader in molti benchmark di LLM, ogni avanzamento di GPT-4 è importante.

Aumentare i limiti dei token del modello per un contesto più ampio

Quindi perché i limiti dei token aumentati sono importanti? Quando si richiede un LLM è possibile includere la conversazione precedente, quindi un vantaggio immediato è che ricorda di cosa si stava parlando in precedenza se si fornisce la cronologia della conversazione in ogni prompt. Questo è utile per fare riferimento a fatti in conversazioni precedenti che potrebbero essere importanti in questo momento. Una finestra di contesto più ampia significa anche che è possibile “precaricare” la chat con informazioni di supporto, come contenuti di documenti e dati.

Ma c’è un lato negativo.

Più token significano costi più elevati e prestazioni più lente perché con l’architettura del transformer i requisiti di memoria e computazionali aumentano quadraticamente (molto più velocemente di una semplice linea retta). Inoltre, ci sono alcune ricerche che suggeriscono che finestre di contesto più lunghe degradino l’accuratezza del LLM (Liu et al, 2023).

Utilizzo di GPT-4-Turbo

Al momento della scrittura, GPT-4-Turbo è disponibile solo in modalità di anteprima, come modello ‘gpt-4-1106-preview’. Per chiamarlo utilizzeremo il pacchetto Python di openai come segue …

import openaiopenai.api_key = '<LA TUA CHIAVE VA QUI>'def run_llm(query, system_prompt, reference_content):    llm_query = {        "temperature": 1.0,        "max_tokens": 2000,        "top_p": 0.95,        "frequency_penalty": 0,        "presence_penalty": 0,    }    response = openai.ChatCompletion.create(        model=model,        messages=[  {                "role":"system",                "content": system_prompt            },            {                "role":"user",                "content": query            }        ],        temperature=llm_query['temperature'],        max_tokens=llm_query['max_tokens'],        top_p=llm_query['top_p'],        frequency_penalty=llm_query['frequency_penalty'],        presence_penalty=llm_query['presence_penalty'],        stop=None    )      answer = response['choices'][0]['message']['content']    return answer

Analisi dei report sulle situazioni di emergenza di ReliefWeb

Esploreremo il limite aumentato dei token di GPT-4-Turbo utilizzandolo per analizzare i report sulle situazioni di emergenza umanitaria sulla straordinaria piattaforma ReliefWeb. Questi report (noti come ‘Sitreps’) sono fondamentali per monitorare e reagire alle catastrofi umanitarie in tutto il mondo. Forniscono anche un corpus di dati testuali che possono essere compressi (riassunti) per adattarsi alla finestra di contesto di GPT-4-Turbo per la nostra analisi.

Costruzione di un corpus di report sulle catastrofi

ReliefWeb dispone di una API davvero fantastica per accedere ai contenuti, quindi la utilizzeremo per estrarre una lista di catastrofi e report sulle situazioni …

import requests  import os  from bs4 import BeautifulSoup import reimport pandas as pdimport PyPDF2 import tracebackimport jsonimport astfrom langchain.text_splitter import RecursiveCharacterTextSplitterimport tiktokendef auto_translate(text):    """    Questa funzione rileva automaticamente la lingua e la traduce in inglese     Parametri:        text(str): Il testo da tradurre    Restituisce:        text (str): Testo tradotto se in un'altra lingua, altrimenti                     l'input text    """    try:        lang = translator.detect(text)        lang = lang.lang        print(f"Lingua rilevata: {lang}")        q = translator.translate(text, dest='en')        text = q.text    except Exception as e:        print("Si è verificata un'eccezione durante la traduzione")    return textdef get_safe_name(name):    """    Questa funzione prende una stringa e restituisce una versione di essa     sicura da utilizzare come nome file.    Parametri:        name (str): La stringa da convertire in un nome file sicuro    Restituisce:        name (str): Il nome file sicuro    """    name = str(name)    name = re.sub("[^0-9a-zA-Z]+", "_", name)    name = re.sub(r"_$","", name)    if len(name) == 0:        name = 'Sconosciuto'     return namedef download_pdf(url, download_path):      """    Funzione per scaricare un PDF da un URL e salvarlo localmente    Parametri:        url (str): Posizione del file PDF online        download_path (str): Cartella in cui salvare il PDF    """    response = requests.get(url)      with open(download_path, 'wb') as f:          f.write(response.content)    def save_text(content, file_path):      """    Funzione per salvare il testo su un file locale    Parametri:        content (str): Testo da salvare        file_path (str): Cartella in cui salvare     """    with open(file_path, 'w') as file:          print(f'Salvataggio {file_path}')        file.write(content)    def extract_text_from_pdf(pdf_path):      """    Funzione per estrarre il testo da un file PDF    Parametri:        pdf_path (str): Percorso del file PDF    Restituisce:        text (str): Testo estratto dal file PDF    """    print(pdf_path)    pdf_reader = PyPDF2.PdfReader(pdf_path)      text = ''      for page_num in range(len(pdf_reader.pages)):          page_obj = pdf_reader.pages[page_num]        text += page_obj.extract_text()      return text  def get_rw_data(keyword, filter, sort, fields, endpoint, limit=10, \                save_body_to_text=False):      """    Funzione per estrarre dati dall'API di ReliefWeb. Per i dettagli dell'API, consultare:    https://apidoc.rwlabs.org/?utm_VoAGI=blog&utm_source=reliefweb+website&utm_campaign=api+doc+launching+2016_06    Parametri:        keyword (str): Stringa di ricerca        filter (dict): Filtro json di ReliefWeb        sort (dict): Ordinamento json di ReliefWeb        fields (list): Elenco dei campi da restituire        endpoint (str): Endpoint API, ad es. report, catastrofi        limit (int): Massimo numero di record da restituire        save_body_to_text (bool) : Flag per salvare il corpo del testo su un file, incluso eventuali PDF sulla pagina    Restituisce:        all_data (pandas dataframe): Dataframe di dati dall'API    """    query = {          "appname": "myapp",          "query": {              "value": keyword        },          "filter":filter,        "sort": sort,        "limit": limit,          "fields": fields    }      endpoint = f"{reliefweb_api_url}/{endpoint}?appname=apidoc&query[value]="    print(f"Recupero di {endpoint} ...")      all_data =[]    response = requests.post(endpoint, json=query)      if response.status_code == 200:          data = response.json()          for article in data["data"]:             article_url = article['fields']['url']               try:                r = article['fields']                print(article_url)                article_response = requests.get(article_url)                  if save_body_to_text:                    soup = BeautifulSoup(article_response.text, 'html.parser')                      main_content = [p.text for p in soup.find_all('p')]                      article_text = ' '.join(main_content)                    save_text(article_text, docs_folder + '/{}.txt'.format(get_safe_name(article['fields']['title'])))                      for link in soup.find_all('a'):                          href = link.get('href')                          if href.endswith('.pdf'):                              download_path = os.path.join(docs_folder, href.split('/')[-1])                              if href.startswith('/attachments'):                                pdf_url = f'{reliefweb_pdf_url}{href}'                            else:                                pdf_url = href                            download_pdf(pdf_url, download_path)                              print(f".    PDF scaricato {download_path} da {pdf_url}")                            article_text = extract_text_from_pdf(download_path)                    r['article_text'] = article_text                    r['reliefweb_query'] = keyword                all_data.append(r)            except Exception as e:                print(f"Si è verificata un'eccezione durante l'estrazione di {article_url}")                tb_str = ''.join(traceback.format_exception(None, e, e.__traceback__))                print(tb_str)        all_data = pd.DataFrame(all_data)        for f in ['disastro','tema']:            if f in list(all_data.columns):                all_data[f] = all_data[f].astype(str)        return all_data      else:          print(f"Richiesta non riuscita con stato {response.status_code} {response.text}")          return None 

Nelle funzioni sopra indicate, alcuni punti di interesse …

  1. Se il contenuto di ReliefWeb si riferisce a un PDF, ne estraiamo il testo
  2. Qualsiasi testo viene tradotto automaticamente in inglese utilizzando l’API di Google Translate
  3. Catturiamo sempre le fonti per l’attribuzione
  4. Non ci siamo preoccupati della paginazione delle risposte dell’API per questa rapida analisi

Ecco come chiamiamo la funzione per ottenere i rapporti sulla situazione di emergenza dal 1° novembre 2023 …

filter = {    "operator": "AND",    "conditions": [        {            "field": "disaster.status",            "value": "in corso"        },        {            "field": "format.name",            "value": "Rapporto sulla situazione"        },        {            "field": "date.created",            "value": {                "from": "2023-11-01T00:00:00+00:00",                "to": "2023-11-30T23:59:59+00:00"            }        }    ]}sort = ["date.created:desc"]endpoint = "reports"fields = {      "include": ["title", "body", "url", "source", "date", "format", "theme",     "country", "status", "primary_country", "disaster", "language", "id"] }  reliefweb_query = ""articles = get_rw_data(reliefweb_query, filter, sort, fields, endpoint, 1000, True)

I rapporti sulla situazione vengono salvati nel sistema di file come file di testo …

for index, row in articles.iterrows():    date = row['date']['created']    source = row['source'][0]['name']    title = row['title']    id = row['id']    filename = f'{get_safe_name(title)}__{id}_{get_safe_name(date)}.txt'    text = f'''        title: {title}        source: {source}        date: {date}        id: {id}        {row['article_text']}    '''    text = text.encode('utf-8','ignore').decode('utf-8','ignore')    print(text)    save_text(text, docs_folder + '/' + filename) 

Comprimere i contenuti utilizzando le rappresentazioni primarie sparse (SPR)

Potremmo semplicemente invitare GPT-4-Turbo con testo grezzo dai rapporti sulla situazione. Tuttavia, gran parte di quel testo è irrelevante, come parole di arresto, intestazioni e piè di pagina, quindi includerle tutte supererebbe molto rapidamente anche i limiti di token incrementati di GPT-4-Turbo. Al suo posto utilizzeremo una tecnica chiamata Rappresentazioni primarie sparse (SPR) per comprimere i documenti nei loro fatti chiave, modificandola leggermente per cercare di preservare le informazioni quantitative.

Ecco il prompt di sistema che forniremo a GPT-4-Turbo per comprimere i nostri documenti …

# MISSIONSei uno scrittore di rappresentazione primaria sparso (SPR). Un SPR è un particolare tipo di utilizzo del linguaggio per compiti avanzati di NLP, NLU e NLG, particolarmente utile per l'ultima generazione di modelli di lingua di grande dimensione (LLM). Ti verranno fornite informazioni dall'UTENTE che dovrai rendere come SPR.# THEORYLLM sono una sorta di rete neurale profonda. Sono stati dimostrati di incorporare conoscenze, abilità e concetti, che vanno dal ragionamento alla pianificazione, e persino alla teoria della mente. Questi sono chiamati abilità latenti e contenuti latenti, definiti collettivamente spazio latente. Lo spazio latente di un LLM può essere attivato con la serie corretta di parole in ingresso, che creeranno uno stato interno utile della rete neurale. Questo non è diverso dal modo in cui delle giuste indicazioni in codice breve possono stimolare una mente umana a pensare in un certo modo. Come le menti umane, i LLM sono associativi, il che significa che è sufficiente utilizzare le associazioni corrette per "attivare" un altro modello a pensare nello stesso modo. L'eccezione sono le metriche quantitative, che DEVONO essere preservate.# METHODOLOGYRendere l'input come un elenco distillato di affermazioni concise, affermazioni, associazioni, concetti, analogie e metafore. L'idea è catturare il maggior numero possibile di concetti, concettualmente, ma con il minor numero possibile di parole, preservando al contempo tutti i dettagli quantitativi. Scrivilo in modo che abbia senso per te, poiché il pubblico futuro sarà un altro modello di linguaggio, non un essere umano.

Questo riassumerà un rapporto di stato di testo grezzo in qualcosa di simile a questo per un rapporto di situazione intitolato “African Polio Laboratory Network Bulletin (settimana 1-42, 2023)” …

- Le informazioni provengono dall'Organizzazione Mondiale della Sanità. - I casi settimanali di dengue sono in diminuzione, ne sono stati segnalati 12.634 questa settimana. - 78 morti correlate alla dengue questa settimana. - Casi cumulativi dal gennaio 2023: 267.680, inclusi 1.333 morti. - Casi in diminuzione in tutte le divisioni tranne Sylhet. - Aumento dei casi di dengue nei distretti di Faridpur, Khulna, Rajshahi, Rajbari. - La sessione di orientamento dell'OMS per gli entomologi a Dhaka si è svolta il 26 ottobre. - Il tasso di mortalità complessivo (CFR) è dello 0,5%, ma dello 0,62% per questa settimana. - La divisione di Dhaka riporta il maggior numero di casi e morti. - In questa settimana, 13.430 persone sono state dimesse dall'ospedale dopo il trattamento. - Rapporto morti uomo-donna: 43% vs 57%. - La maggior parte delle morti si verifica nel gruppo di età compreso tra i 16 e i 55 anni. - Quattro tipi di virus della dengue circolano: DENV-1 (2,2%), DENV-2 (68,1%), DENV-3 (25,4%), DENV-4 (0,2%). - La settimana di prevenzione e pulizia della dengue è stata lanciata a livello nazionale dal 29 ottobre al 4 novembre. - Entomologo esperto dell'OMS dispiegato in Bangladesh per supporto tecnico nella risposta all'epidemia. - Nei campi Rohingya, i casi settimanali di dengue continuano a diminuire. I casi cumulativi totali sono 12.969, inclusi 17 decessi (CFR: 0,1%).

Che è ovviamente molto meno testo rispetto al documento originale.

Non consiglierei di utilizzare questa compressione senza un’analisi e verifiche significative per controllare l’omissione di informazioni, ma per i nostri test sarà sufficiente.

Ecco il codice per la compressione dei report…

# gpt4 turbo è 128k chunk_size = 100000llm_query = {    "prompt": "",    "temperature": 1.0,    "max_tokens": 2000,    "top_p": 0.95,    "frequency_penalty": 0,    "presence_penalty": 0,    "system_prompt": """        # MISSION        Sei uno scrittore Sparse Priming Representation (SPR). Un SPR è un         particolare tipo di uso del linguaggio per NLP, NLU e NLG         avanzati, particolarmente utile per l'ultima generazione di Large Language         Models (LLMs). Ti verranno fornite informazioni dall'UTENTE che dovrai rappresentare come SPR.        # TEORIA        I LLM sono una sorta di rete neurale profonda. Sono stati dimostrati         essere in grado di incorporare conoscenze, abilità e concetti,         dall'elaborazione del ragionamento alla pianificazione, e persino alla         teoria della mente. Questi sono chiamati abilità latenti e contenuti latenti,         definiti collettivamente spazio latente. Lo spazio latente di un LLM può essere         attivato con la corretta serie di parole in ingresso, creando uno stato         interno utile alla rete neurale. Non è diverso da come i segnali corti della scrittura         possono predisporre una mente umana a pensare in un certo modo. Come le menti umane,         i LLM sono associativi, il che significa che è sufficiente utilizzare le corrette         associazioni per "predisporre" un altro modello a pensare nello stesso modo.         L'eccezione sono le misure quantitative, che DEVONO essere preservate.        # METODOLOGIA        Rappresenta l'input come un elenco distillato di affermazioni sintetiche,         concetti, associazioni, analogie e metafore. L'idea è di catturare il più         possibile, concettualmente, ma con il minor numero di parole possibile,         preservando al contempo tutti i dettagli quantitativi. Scrivilo in modo che abbia         un senso per te, poiché il pubblico futuro sarà un altro modello di linguaggio,         non un essere umano.    """}# Salva i testifor index, row in articles.iterrows():    date = row['date']['created']    source = row['source'][0]['name']    report = row['title']    id = row['id']    text = row['article_text']    primary_country = row['primary_country']['name']    disaster = ''    disaster_types = ''    for d in ast.literal_eval(row['disaster']):        disaster += f"{d['name']}; "        for t in d['type']:            if 'primary' in t and t['primary'] == True:                disaster_types += f"{t['name']}; "    d = {        "disaster": disaster,        "date": date,        "disaster_types": disaster_types    }    prefix = ""    filename = f'{get_safe_name(report)}__{id}_{get_safe_name(date)}.txt'    header = f'- report: "{report}"\n- disaster: "{disaster}"\n' + \             f'- disaster_types: "{disaster_types}"\n' + \             f'- primary_country: "{primary_country}"\n- source: "{source}"\n' + \             f'- date: "{date}"\n- id: "{id}"\n'    text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(        chunk_size=chunk_size, chunk_overlap=100    )    texts = text_splitter.split_text(text)    print(f"\n\n================ {report} =================\n")    print(primary_country)    print(disaster)    print(len(texts))    summarized_text = ''    for i, t in enumerate(texts):        response = openai.ChatCompletion.create(        model=model,        messages=[  {                "role":"system",                "content":llm_query['system_prompt']            },            {                "role":"user",                "content":t            }        ],        temperature=llm_query['temperature'],        max_tokens=llm_query['max_tokens'],        top_p=llm_query['top_p'],        frequency_penalty=llm_query['frequency_penalty'],        presence_penalty=llm_query['presence_penalty'],        stop=None)          summary = response['choices'][0]['message']['content']        summarized_text += "\n" + summary    summarized_text = auto_translate(summarized_text)    summarized_text = header + summarized_text    summarized_text = summarized_text.split("\n")    summarized_text_prefixed = ''    for s in summarized_text:        summarized_text_prefixed += f"{prefix}{s}\n"    print(summarized_text_prefixed)    save_text(summarized_text_prefixed, docs_folder2 + '/' + filename)

Noterete quanto sopra abbiamo aggiunto alcuni metadati sul report oltre al riepilogo SPR restituito da GPT-4-Turbo. I report compressi vengono quindi salvati come file di testo.

Estrazione di un elenco di disastri di alto livello

Estrarremo anche un elenco di disastri di alto livello da ReliefWeb da utilizzare nel nostro prompt di sistema, come aiuto alle richieste di informazioni …

filter = {    "operatore": "AND",    "condizioni": [        {            "campo": "stato",            "valore": "in corso"        },        {            "campo": "data.evento",            "valore": {                "da": "2020-01-01T00:00:00+00:00",                "a": "2023-11-30T23:59:59+00:00"            }        }    ]}sort = ["data.evento:descrizione"]endpoint = "disastri"campi = {      "include": ["nome", "descrizione", "data", "url", "id","stato","glide"] } reliefweb_query = ""disastri = get_rw_data(reliefweb_query, filter, sort, campi, endpoint, 1000, False)display(disastri)disastri.to_csv('disastri.csv')

Questo ci fornisce un elenco sintetico …

Elenco dei disastri estratto utilizzando l'endpoint dei disastri dell'API di ReleiefWeb

Creazione di un prompt per GPT-4-Turbo

Ora abbiamo un elenco di disastri e rapporti di situazione compressi – dal 1° novembre al 10 novembre – elencando dati chiave di quei disastri.

Uniamoli in un unico file di testo da utilizzare come parte del prompt di sistema per GPT-4-Turbo …

disastri = pd.read_csv('disastri.csv')contenuto_concatenato = "=========== questa sezione fornisce un elenco di DISASTRI =========== \n\n "+ disastri.to_csv()contenuto_concatenato += "\n\n=========== questa sezione fornisce REPORT sui disastri per ogni disastro =========== "for f in os.listdir(docs_folder2):  with open(f"{docs_folder2}/{f}", "r") as file:      contenuto_file = file.read()      contenuto_concatenato += f"\n\n----- report: {f} ----- \n\n"      contenuto_concatenato += contenuto_file + "\n\n"

Quanti token e quale è il costo?

def num_tokens_from_string(stringa: str, nome_codifica: str) -> int:    codifica = tiktoken.get_encoding(nome_codifica)    num_token = len(codifica.encode(stringa))    costo_token_gpt4_per_1000 = 0.01    costo = (num_token/1000.0)*costo_token_gpt4_per_1000    return num_token, costooken, costo = num_tokens_from_string(contenuto_concatenato,"cl100k_base")OpenAI Tokens: 82001 (0,82 USD)

Quindi, dato il costo di 0,01 USD per 1.000 token di input, il testo creato sopra ha un costo di 0,82 USD per un prompt. C’è anche un costo dei token di completamento, 0,03 USD ogni 1.000 token, ma questo dovrebbe essere molto inferiore al costo di input in quanto ci sono molti meno token.

Ouch!

Sapevamo che questa tecnica forzata non è il modo migliore per affrontare il nostro compito particolare, ma il costo elevato è un’altra ragione.

Ora che abbiamo il nostro testo, possiamo costruire un prompt di sistema …

def run_llm(query, contenuto_riferimento):    llm_query = {        "temperatura": 1.0,        "max_tokens": 2000,        "top_p": 0.95,        "penalità_frequenza": 0,        "penalità_presenza": 0,    }    risposta = openai.ChatCompletion.create(        modello=modello,        messaggi=[  {                "ruolo":"sistema",                "contenuto": f"""Sei un bot sui disastri di ReliefWeb.                 Fornisci informazioni sui disastri.                                 Se viene richiesto un elenco di disastri, fornisci solo l'elenco                 SOLO utilizzando la sezione 'Disastri' qui sotto.                                 Se viene richiesti dettagli su un disastro, estrai tali informazioni                 dalla sezione 'Rapporti di situazione' qui sotto.                                   {contenuto_riferimento}"""            },            {                "ruolo":"utente",                "contenuto": query            }        ],        temperatura=llm_query['temperatura'],        max_tokens=llm_query['max_tokens'],        top_p=llm_query['top_p'],        penalità_frequenza=llm_query['penalità_frequenza'],        penalità_presenza=llm_query['penalità_presenza'],        stop=None    )      risposta = response['choices'][0]['message']['contenuto']    return risposta

Noterai che il prompt di sistema include istruzioni su quali sezioni del testo concatenato utilizzare per tipi diversi di informazioni. Attraverso alcune veloci sperimentazioni del prompt – non lo chiamerei realmente ‘ingegneria’ – sono stati ottenuti risultati migliori.

Test del nostro Bot per le relazioni sulle situazioni di disastro umanitario

OK, proviamo…

risposta = run_llm("Qual è l'ultimo stato riguardo al terremoto in Nepal di quest'anno?", concatenated_content)print(risposta)

L'ultimo stato riguardante il terremoto in Nepal al novembre 2023 è il seguente:- Terremoto: Nepal occidentale, magnitudo 6.4, avvenuto il 3 novembre 2023, con epicentro a Ramidanda, Jajarkot.- Vittime: 154 morti, 364+ feriti.- Spostamenti: Circa 250.000 persone colpite, con un numero significativo di abitazioni danneggiate o distrutte.- Infrastrutture: Oltre 62.000 case in 13 distretti hanno subito danni (26.557 completamente, 35.455 parzialmente). Anche diversi edifici governativi sono stati danneggiati.- Risposta umanitaria: Le Nazioni Unite e altre organizzazioni umanitarie sono state attive negli sforzi di soccorso, fornendo tende mediche, spazi a misura di bambino, forniture per l'igiene dell'acqua e supporto psicosociale, tra altre forme di assistenza.- Ripresa e riabilitazione: La fase di ripresa e riabilitazione è in fase di pianificazione, con rinforzi internazionali che arrivano per aiutare nella coordinazione e nello sviluppo di strategie.- Servizi educativi e sanitari: L'educazione è stata interrotta per circa 80.000 bambini a causa delle scuole danneggiate, e i servizi sanitari sono stati influenzati, aumentando il rischio di malnutrizione e complicando la cura materna e neonatale si prega di notare che questa è una sintesi condensata dei dati disponibili fino al 10 novembre 2023, e ulteriori aggiornamenti potrebbero seguire man mano che la situazione evolve e si effettuano ulteriori valutazioni.

Nel complesso, questa è una buona sintesi del disastro. I fatti concordano bene con la pagina sui disastri di ReliefWeb (nota che questa pagina potrebbe cambiare poiché questo articolo è stato scritto, mentre il disastro evolve) e il ultimo rapporto di situazione utilizzato per questo studio.

In realtà, c’è un dato che non è del tutto allineato, i dati indicano che in modo tragico sono morte 153 persone, mentre il modello restituisce 154.

risposta = run_llm("Quante persone sono morte nel terremoto in Nepal nel 2023?", concatenated_content)print(risposta)Nel terremoto in Nepal del novembre 2023, ci sono stati 153 morti.

Quindi è ‘conosciuto’, ma fuorviante nel primo prompt. Come per tutte le applicazioni di LLM, la convalida e i controlli sono fondamentali per individuare problemi come questo.

Otteniamo informazioni sulle organizzazioni che creano i rapporti sulla situazione (per il periodo dal 1° al 10 novembre)…

risposta = run_llm("Elenca le organizzazioni che forniscono rapporti sulla situazione per il terremoto in Nepal", concatenated_content)print(risposta)Le organizzazioni che forniscono rapporti sulla situazione per il terremoto in Nepal includono:- Ufficio delle Nazioni Unite per il Coordinamento degli Affari Umanitari (OCHA)- Croce Rossa Nepal- Federazione Internazionale delle Società di Croce Rossa e Mezzaluna Rossa (IFRC)- Coordinatore Residente delle Nazioni Unite in Nepal- Organizzazione Mondiale della Sanità (OMS)- Fondo delle Nazioni Unite per l'Infanzia (UNICEF)- Team delle Nazioni Unite in Nepal

Rispetto alla stessa query su ReliefWeb, sembra corretto.

Facciamo alcune domande più approfondite…

risposta = run_llm("Quanti sfollati sono bambini?", concatenated_content)print(risposta)Nei dati forniti, ci sono riferimenti a bambini colpiti da disastri in diversi rapporti, ma il numero specifico di bambini sfollati non è menzionato esplicitamente in nessuno degli estratti. Sarebbe necessario esaminare rapporti più dettagliati o fonti di dati specifiche che si concentrano specificamente sulle cifre relative allo sfollamento dei bambini per determinare il numero esatto dei bambini coinvolti nello sfollamento.

Anche osservando i rapporti sulla situazione, non sono riuscito a trovare queste informazioni. Tuttavia, è necessario un controllo più dettagliato per stabilire se ciò sia vero o meno.

Chiediamo informazioni sulle possibili malattie e gli impatti sulla salute…

risposta = run_llm("Quali sono i rischi di malattie causati dal terremoto in Nepal nel 2023?", concatenated_content)print(risposta)I rischi di malattie causati dal terremoto in Nepal nel 2023, come riportato da UNICEF nel loro Rapporto sulla Situazione Umanitaria n. 2, sono principalmente incentrati sulla malnutrizione, in particolare tra i bambini di età inferiore ai cinque anni, e lo stress psicosociale che colpisce la popolazione interessata. La interruzione dei servizi sanitari e WASH (acqua, igiene e servizi sanitari) a causa del terremoto ha ulteriormente aggravato i rischi per la salute.I principali rischi di malattie e preoccupazioni per la salute includono:1. Malnutrizione: Il terremoto e le sue conseguenze hanno interrotto la catena di approvvigionamento alimentare, aumentando il rischio di malnutrizione tra le popolazioni vulnerabili, in particolare i bambini.2. Salute materna e neonatale: Le donne in gravidanza e i neonati potrebbero affrontare maggiori rischi per la salute a causa della interruzione dei servizi di assistenza sanitaria e della mancanza di accesso a cure mediche e strutture essenziali.3. Stress psicosociale: Il trauma causato dal terremoto, la perdita di persone care e lo sfollamento possono portare a un significativo stress psicosociale e problemi di salute mentale.4. Lesioni e salute fisica: Con molte persone ferite nella fase successiva al terremoto, c'è un maggiore bisogno di trattamento medico per lesioni fisiche e cure psicologiche. 5. Malattie trasmissibili: L'affollamento negli alloggi temporanei può portare alla diffusione di malattie trasmissibili, in particolare in assenza di adeguate strutture igienico-sanitarie.6. Malattie trasmesse dall'acqua e da vettori: La mancanza di acqua pulita e servizi igienico-sanitari aumenta il rischio di malattie trasmesse dall'acqua come diarrea, colera e dissenteria. Sussiste anche il rischio di malattie trasmesse da vettori come malaria e febbre dengue.7. Malattie non trasmissibili: La interruzione dei servizi sanitari di routine può influire sulla gestione e il trattamento delle malattie croniche non trasmissibili.8. Interruzione della immunizzazione di routine: La potenziale interruzione dei servizi di vaccinazione di routine può aumentare il rischio di malattie prevenibili con il vaccino.In risposta a questi rischi per la salute, UNICEF e altri partner del settore sanitario forniscono servizi sanitari, forniture mediche e supporto psicosociale, oltre a garantire un continuo accesso a una buona nutrizione per i bambini e le madri.

Osservando il rapporto UNICEF sui dati, anche con la nostra sintesi SPF, sembra che quanto sopra catturi i punti principali. Tuttavia, qui abbiamo solo il rapporto numero 1 nei dati utilizzati, ma sopra viene menzionato il rapporto numero 2. Un’altra piccola allucinazione, che dimostra ancora una volta che qualsiasi risposta LLM ha bisogno di una verifica automatica.

Conclusioni

Questa è un’analisi molto rapida per avere un’idea di quanto bene si comporti GPT-4-Turbo, con la sua finestra di contesto aumentata a 128k e un miglioramento nel seguire le istruzioni, includendo tutti i dati testuali necessari per il recupero delle informazioni come input di sistema, senza alcun altro processo. Questo approccio di forza bruta è la migliore tecnica per il nostro compito?

Probabilmente no, almeno ancora non lo è.

La performance è una considerazione seria. Le richieste richiedevano 30 secondi o più, non ottimo per un’esperienza utente piacevole.

Il costo è anche proibitivo. Con più token necessari per fornire un corpus completo con ogni richiesta, c’è un aumento dei costi – in questa analisi $0.82 per ogni richiesta! – quindi altre tecniche saranno indubbiamente più interessanti per molte organizzazioni, almeno finché i costi delle LLM rimangono elevati. Detto questo, mi viene in mente il costo dello storage nel corso degli anni, e forse vedremo lo stesso calo dei costi per le LLM nel tempo.

Alternative come generare codice per interrogare i dati, utilizzare funzioni registrate con le LLM e più agenti per convalidare i risultati potrebbero offrire opzioni più economiche e accurate. Inoltre, eliminerebbero la necessità di comprimere i documenti per farli rientrare nella finestra di contesto, evitando così la perdita di informazioni.

Detto ciò, siamo stati in grado di dimostrare che interrogando GPT-4-Turbo è possibile supportare il recupero di informazioni di base su un corpus di documenti compressi forniti come input di sistema. Ciò ha alcuni vantaggi nel suo essere molto semplice da implementare: basta fornire alle LLM tutto ciò che si ha e fare domande. Con l’avanzare dell’intelligenza artificiale e la diminuzione dei costi, questa potrebbe diventare una tecnica molto comune in futuro.