Creare un Suggester intelligente per l’itinerario di viaggio con LangChain, l’API di Google Maps e Gradio (Parte 1)

Creare un Suggester intelligente per l'itinerario di viaggio con LangChain, l'API di Google Maps e Gradio (Prima parte)

Scopri come creare un’applicazione che potrebbe ispirare il tuo prossimo viaggio su strada

Questo articolo è parte 1 di una serie di tre parti in cui costruiamo un’applicazione per suggerire itinerari di viaggio utilizzando OpenAI e Google APIs e la mostriamo in un’interfaccia utente semplice generata con gradio. In questa parte, iniziamo discutendo l’ingegneria delle prompt per questo progetto. Vuoi solo vedere il codice? Trovalo qui.

1. Motivazione

Dal lancio di ChatGPT alla fine del 2022, c’è stata un’esplosione di interesse per i modelli di linguaggio di grande dimensione (LLM) e il loro utilizzo in prodotti rivolti ai consumatori come chatbot e motori di ricerca. Meno di un anno dopo, abbiamo accesso a una moltitudine di LLM open source disponibili nei modelli hub come Hugging Face, servizi di hosting dei modelli come Lamini e API a pagamento come OpenAI e PaLM. È sia eccitante che un po’ travolgente vedere quanto rapidamente si stia sviluppando questo campo, con nuovi strumenti e paradigmi di sviluppo che sembrano emergere ogni poche settimane.

Qui useremo solo una piccola parte di questa varietà di strumenti per costruire un’applicazione utile che potrebbe aiutarci nella pianificazione di viaggi. Quando si pianifica una vacanza, è spesso bello ricevere suggerimenti da qualcuno che è stato lì prima e ancora meglio vedere quei suggerimenti disposti su una mappa. In assenza di questi consigli, a volte mi limito a consultare Google Maps nell’area generale che desidero visitare e selezionare casualmente alcuni luoghi che sembrano interessanti. Forse questo processo è divertente, ma è inefficace e probabile che si stia perdendo qualcosa. Non sarebbe bello avere uno strumento che possa darti un sacco di suggerimenti con solo alcune preferenze di alto livello?

Ecco esattamente quello che cercheremo di costruire: un sistema che possa fornire suggerimenti per itinerari di viaggio dati alcuni criteri di alto livello, qualcosa come “Ho 3 giorni per esplorare San Francisco e amo i musei d’arte”. La funzione di IA generativa di Google Search e ChatGPT possono già produrre risultati creativi per richieste come questa, ma vogliamo andare oltre e produrre un vero e proprio itinerario con tempi di viaggio e una bella mappa per aiutare l’utente nell’orientamento.

Questo è quello che costruiremo: un sistema per generare suggerimenti di viaggio con una mappa di base che mostra il percorso e i waypoint forniti dal LLM

Lo scopo è di familiarizzare maggiormente con gli strumenti necessari per costruire un servizio di questo tipo piuttosto che effettivamente distribuire l’applicazione, ma lungo il percorso impareremo un po’ di ingegneria delle prompt, orchestrazione di LLM con LangChain, utilizzo delle direzioni dell’API di Google Maps per estrarre indicazioni e visualizzazione dei risultati con leafmap e gradio. È incredibile quanto rapidamente questi strumenti ti consentano di creare un POC per sistemi come questo, ma come sempre le vere sfide si trovano nella valutazione e nella gestione dei casi limite. Lo strumento che costruiremo è lontano dall’essere perfetto e se qualcuno è interessato ad aiutarmi a svilupparlo ulteriormente, sarebbe fantastico.

2. Strategia di promozione

Questo progetto farà uso delle API di OpenAI e Google PaLM. Puoi ottenere le chiavi API creando account qui e qui. Al momento della scrittura, l’API di Google è disponibile solo in modo limitato ed è in lista d’attesa, ma dovrebbe richiedere solo pochi giorni per ottenere l’accesso.

L’uso di dotenv è un modo facile per evitare di dover copiare e incollare le chiavi API nel tuo ambiente di sviluppo. Dopo aver creato un file .env con le seguenti righe

OPENAI_API_KEY = {tua chiave open ai}GOOGLE_PALM_API_KEY = {tua chiave api di Google Palm}

Possiamo utilizzare questa funzione per caricare le variabili pronte per l’uso successivo da LangChain, ad esempio

from dotenv import load_dotenvfrom pathlib import Pathdef load_secets():    load_dotenv()    env_path = Path(".") / ".env"    load_dotenv(dotenv_path=env_path)    open_ai_key = os.getenv("OPENAI_API_KEY")    google_palm_key = os.getenv("GOOGLE_PALM_API_KEY")    return {        "OPENAI_API_KEY": open_ai_key,        "GOOGLE_PALM_API_KEY": google_palm_key,    }

Ora, come dovremmo progettare gli input per un servizio di agenzia di viaggio? L’utente sarà libero di inserire qualsiasi testo desideri, quindi vogliamo prima determinare se la loro richiesta è valida o meno. Vogliamo sicuramente segnalare qualsiasi richiesta che contenga contenuti dannosi, come richieste di un itinerario con intenti maligni.

Vogliamo anche filtrare le domande non correlate ai viaggi: senza dubbio, LLM potrebbe fornire una risposta a tali domande, ma sono al di là dello scopo di questo progetto. Infine, vogliamo anche identificare le richieste irragionevoli come “Voglio volare sulla luna” o “Voglio fare un viaggio su strada di tre giorni da New York a Tokyo”. Di fronte a una richiesta irragionevole come questa, sarebbe fantastico se il modello potesse spiegare perché sia irragionevole e suggerire una modifica che possa aiutare.

Una volta che la richiesta viene convalidata, possiamo procedere fornendo un itinerario suggerito, che idealmente dovrebbe contenere gli indirizzi specifici dei punti intermedi in modo che possano essere inviati a un’API di mappatura o indicazioni come Google Maps.

L’itinerario dovrebbe essere leggibile dall’essere umano, con sufficienti dettagli affinché l’utente lo trovi utile come suggerimento autonomo. Grandi LLM ottimizzati per le istruzioni, come ChatGPT, sembrano essere bravi a fornire risposte di questo tipo, ma dobbiamo assicurarci che gli indirizzi dei punti intermedi vengano estratti in modo coerente.

Quindi ci sono tre fasi distinte qui:

  1. Convalidare la richiesta
  2. Produrre l’itinerario
  3. Estrarre i punti intermedi in un formato che possa essere comprensibile dall’API di Google Maps

Potrebbe essere possibile progettare un input che possa gestire tutte e tre le fasi in una chiamata, ma per facilità di debugging le divideremo in tre chiamate LLM, una per ogni parte.

Fortunatamente, PydanticOutputParser di LangChain può davvero aiutare in questo, fornendo un insieme di input predefiniti che incoraggiano i LLM a formattare le loro risposte in modo conforme a uno schema di output.

3. L’input di convalida

Diamo un’occhiata all’input di convalida, che possiamo incapsulare in una classe di template per renderlo più facile da contenere e iterare su diverse versioni.

from langchain.prompts.chat import (    ChatPromptTemplate,    SystemMessagePromptTemplate,    HumanMessagePromptTemplate,)from langchain.output_parsers import PydanticOutputParserfrom pydantic import BaseModel, Fieldclass Validation(BaseModel):    plan_is_valid: str = Field(        description="Questo campo è 'sì' se il piano è fattibile, 'no' altrimenti"    )    updated_request: str = Field(description="La tua modifica al piano")class ValidationTemplate(object):    def __init__(self):        self.system_template = """      Sei un agente di viaggio che aiuta gli utenti a pianificare emozionanti viaggi.      La richiesta dell'utente sarà contrassegnata da quattro hashtag. Determina se la richiesta dell'utente      è ragionevole e realizzabile nei vincoli che hanno imposto.      Una richiesta valida dovrebbe contenere quanto segue:      - Una località di partenza e arrivo      - Una durata del viaggio ragionevole data la località di partenza e arrivo      - Altri dettagli, come gli interessi dell'utente e/o la modalità di trasporto preferita      Qualsiasi richiesta che contenga attività potenzialmente dannose non è valida, indipendentemente da quali      altri dettagli vengano forniti.      Se la richiesta non è valida, impostare      plan_is_valid = 0 e utilizzare la tua esperienza di viaggiatore per apportare modifiche alla richiesta,      mantenendo la tua richiesta revisionata entro le 100 parole.      Se la richiesta sembra ragionevole, impostare plan_is_valid = 1 e      non modificare la richiesta.      {format_instructions}    """        self.human_template = """      ####{query}####    """        self.parser = PydanticOutputParser(pydantic_object=Validation)        self.system_message_prompt = SystemMessagePromptTemplate.from_template(            self.system_template,            partial_variables={                "format_instructions": self.parser.get_format_instructions()            },        )        self.human_message_prompt = HumanMessagePromptTemplate.from_template(            self.human_template, input_variables=["query"]        )        self.chat_prompt = ChatPromptTemplate.from_messages(            [self.system_message_prompt, self.human_message_prompt]        )

La nostra classe Validation contiene le definizioni dello schema di output per la query, che sarà un oggetto JSON con due chiavi plan_is_valid e updated_request. All’interno di ValidationTemplate utilizziamo le utili classi di template di LangChain per costruire il nostro prompt e creare anche un oggetto parser con PydanticOutputParser. Questo converte il codice Pydantic in Validation in un insieme di istruzioni che possono essere passate all’LLM insieme alla query. Possiamo quindi includere il riferimento a queste istruzioni di formato nel template di sistema. Ogni volta che viene chiamata l’API, vogliamo che sia sia il system_message_prompt che l’human_message_prompt siano inviati all’LLM, ecco perché li raggruppiamo insieme nel chat_prompt.

Dato che questa non è realmente un’applicazione di chatbot (anche se potrebbe diventarlo!), potremmo semplicemente inserire entrambi i template di sistema ed umani nella stessa stringa e ottenere la stessa risposta.

Ora possiamo creare una classe Agent che utilizza LangChain per chiamare l’API LLM con il template definito sopra. Qui stiamo utilizzando ChatOpenAI, ma può essere sostituito con GooglePalm se si preferisce.

Si noti che qui facciamo anche uso di LLMChain e SequentialChain di LangChain, anche se stiamo effettuando una singola chiamata all’LLM. Questo è probabilmente eccessivo, ma potrebbe essere utile per la estendibilità in futuro se volessimo aggiungere un’altra chiamata, ad esempio all’API di moderazione OpenAI, prima che venga eseguita la catena di validazione.

import openaiimport loggingimport time# per Palmfrom langchain.llms import GooglePalm# per OpenAIfrom langchain.chat_models import ChatOpenAIfrom langchain.chains import LLMChain, SequentialChainlogging.basicConfig(level=logging.INFO)class Agent(object):    def __init__(        self,        open_ai_api_key,        model="gpt-3.5-turbo",        temperature=0,        debug=True,    ):        self.logger = logging.getLogger(__name__)        self.logger.setLevel(logging.INFO)        self._openai_key = open_ai_api_key        self.chat_model = ChatOpenAI(model=model, temperature=temperature, openai_api_key=self._openai_key)        self.validation_prompt = ValidationTemplate()        self.validation_chain = self._set_up_validation_chain(debug)    def _set_up_validation_chain(self, debug=True):              # make validation agent chain        validation_agent = LLMChain(            llm=self.chat_model,            prompt=self.validation_prompt.chat_prompt,            output_parser=self.validation_prompt.parser,            output_key="validation_output",            verbose=debug,        )                # add to sequential chain         overall_chain = SequentialChain(            chains=[validation_agent],            input_variables=["query", "format_instructions"],            output_variables=["validation_output"],            verbose=debug,        )        return overall_chain    def validate_travel(self, query):        self.logger.info("Validating query")        t1 = time.time()        self.logger.info(            "Calling validation (model is {}) on user input".format(                self.chat_model.model_name            )        )        validation_result = self.validation_chain(            {                "query": query,                "format_instructions": self.validation_prompt.parser.get_format_instructions(),            }        )        validation_test = validation_result["validation_output"].dict()        t2 = time.time()        self.logger.info("Time to validate request: {}".format(round(t2 - t1, 2)))        return validation_test

Per eseguire un esempio, possiamo provare il seguente codice. L’impostazione debug=True attiverà la modalità di debug di LangChain, che stampa la progressione del testo della query mentre passa attraverso le varie classi di LangChain durante la chiamata all’LLM.

secrets = load_secets()travel_agent = Agent(open_ai_api_key=secrets[OPENAI_API_KEY],debug=True)query = """        Voglio fare un viaggio di 5 giorni da Cape Town a Pretoria in Sudafrica.        Voglio visitare luoghi remoti con vista sulle montagne.        """travel_agent.validate_travel(query)

Questa query sembra ragionevole, quindi otteniamo un risultato come questo

INFO:__main__:Validating queryINFO:__main__:Calling validation (model is gpt-3.5-turbo) on user inputINFO:__main__:Time to validate request: 1.08{'plan_is_valid': 'yes', 'updated_request': ''}

Adesso testiamo cambiando la query con qualcosa di meno ragionevole, come

query = """        Voglio fare una camminata da Città del Capo a Pretoria in Sudafrica.        Voglio visitare luoghi remoti con vista sulle montagne        """

Il tempo di risposta è più lungo perché ChatGPT sta cercando di fornire una spiegazione del perché la query non è valida e sta generando quindi più token.

INFO:__main__:Convalida della queryINFO:__main__:Chiamata alla convalida (il modello è gpt-3.5-turbo) sull'input dell'utenteINFO:__main__:Tempo per convalidare la richiesta: 4.12{'plan_is_valid': 'no', 'updated_request': 'Passeggiare da Città del Capo a Pretoria in Sudafrica non è ...' a

4. La richiesta dell’itinerario

Se una query è valida, può passare alla fase successiva, che è la richiesta dell’itinerario. Qui vogliamo che il modello restituisca un dettagliato piano di viaggio suggerito, che dovrebbe essere sotto forma di un elenco puntato con gli indirizzi dei punti intermedi e alcuni consigli su cosa fare in ogni luogo. Questa è davvero la parte principale “generativa” del progetto e ci sono molti modi per progettare una query per ottenere buoni risultati qui. Il nostro ItineraryTemplate ha questo aspetto

class ItineraryTemplate(object):    def __init__(self):        self.system_template = """      Sei un agente di viaggio che aiuta gli utenti a pianificare entusiasmanti viaggi.      La richiesta dell'utente sarà indicata da quattro hashtags. Converti la      richiesta dell'utente in un'itinerario dettagliato che descriva i luoghi      che dovrebbero visitare e le cose che dovrebbero fare.      Cerca di includere l'indirizzo specifico di ogni luogo.      Ricordati di tenere conto delle preferenze dell'utente e del tempo a disposizione,      e fornisci loro un itinerario che sia divertente e fattibile date le loro limitazioni.      Restituisci l'itinerario come un elenco puntato con chiari punti di partenza e di arrivo.      Assicurati di menzionare il tipo di trasporto per il viaggio.      Se non vengono indicati punti di partenza e di arrivo specifici, scegline alcuni che ritieni adatti e forni indirizzi specifici.      La tua output deve essere solo l'elenco e nient'altro.    """        self.human_template = """      ####{query}####    """        self.system_message_prompt = SystemMessagePromptTemplate.from_template(            self.system_template,        )        self.human_message_prompt = HumanMessagePromptTemplate.from_template(            self.human_template, input_variables=["query"]        )        self.chat_prompt = ChatPromptTemplate.from_messages(            [self.system_message_prompt, self.human_message_prompt]        )

Si noti che qui non c’è bisogno di un parser Pydantic perché vogliamo che l’output sia una stringa anziché un oggetto JSON.

Per utilizzarlo, possiamo aggiungere un nuovo LLMChain alla classe Agent, che ha questo aspetto

        travel_agent = LLMChain(            llm=self.chat_model,            prompt=self.itinerary_prompt.chat_prompt,            verbose=debug,            output_key="agent_suggestion",        )

Qui non abbiamo impostato l’argomento max_tokens durante l’istanziazione del chat_model, il che permette al modello di decidere la lunghezza del suo output. In particolare, con GPT4 questo può rendere il tempo di risposta piuttosto lungo (oltre 30 secondi in alcuni casi). Curiosamente, i tempi di risposta di PaLM sono considerevolmente più brevi.

5. La richiesta di estrazione dei punti intermedi

Utilizzando la richiesta dell’itinerario potremmo ottenere un bel elenco di punti intermedi, forse qualcosa del genere

- Giorno 1:  - Iniziate a Berkeley, CA  - Guidate fino a Redwood National and State Parks, CA (1111 Second St, Crescent City, CA 95531)  - Esplorate le splendide foreste di sequoie e godetevi la natura  - Guidate fino a Eureka, CA (531 2nd St, Eureka, CA 95501)  - Gustatevi la cucina locale ed esplorate la città affascinante  - Pernottate a Eureka, CA- Giorno 2:  - Iniziate a Eureka, CA  - Guidate fino a Crater Lake National Park, OR (Crater Lake National Park, OR 97604)  - Ammirate il lago blu mozzafiato e percorrete i sentieri panoramici  - Guidate fino a Bend, OR (Bend, OR 97701)  - Fatevi viziare dalla scena gastronomica locale ed esplorate la città vibrante  - Pernottate a Bend, OR- Giorno 3:  - Iniziate a Bend, OR  - Guidate fino a Mount Rainier National Park, WA (55210 238th Ave E, Ashford, WA 98304)  - Godetevi le spettacolari viste sulla montagna e percorrete i sentieri  - Guidate fino a Tacoma, WA (Tacoma, WA 98402)  - Assaggiate le deliziose opzioni culinarie ed esplorate le attrazioni della città  - Pernottate a Tacoma, WA- Giorno 4:  - Iniziate a Tacoma, WA  - Guidate fino a Olympic National Park, WA (3002 Mount Angeles Rd, Port Angeles, WA 98362)  - Esplorate i vari ecosistemi del parco e ammirate la bellezza naturale  - Guidate fino a Seattle, WA (Seattle, WA 98101)  - Sperimentate la vivace scena gastronomica e visitate le attrazioni più popolari  - Pernottate a Seattle, WA- Giorno 5:  - Iniziate a Seattle, WA  - Esplorate altre attrazioni della città e gustatevi la cucina locale  - Concluite il viaggio a Seattle, WA

Ora dobbiamo estrarre gli indirizzi dei punti intermedi in modo da poter procedere alla fase successiva, che consiste nel tracciarli su una mappa e chiamare l’API delle indicazioni di Google Maps per ottenere le indicazioni tra di essi.

Per fare ciò, faremo un’altra chiamata a LLM e utilizzeremo nuovamente PydanicOutputParser per assicurarci che il nostro output sia formattato correttamente. Per comprendere il formato qui, è utile considerare brevemente cosa vogliamo fare nella prossima fase di questo progetto (coperta nella parte 2). Faremo una chiamata all’API di Google Maps Python, che appare così:

import googlemapsgmaps = googlemaps.Client(key=google_maps_api_key)directions_result = gmaps.directions(            start,            end,            waypoints=waypoints,            mode=transit_type,            units="metric",            optimize_waypoints=True,            traffic_model="best_guess",            departure_time=start_time,)

Dove start e end sono indirizzi in formato stringa, e waypoints è una lista di indirizzi che devono essere visitati in mezzo.

Lo schema richiesto per l’estrazione dei punti intermedi pertanto appare così:

class Trip(BaseModel):    start: str = Field(description="indirizzo di partenza del viaggio")    end: str = Field(description="indirizzo di destinazione del viaggio")    waypoints: List[str] = Field(description="lista di punti intermedi")    transit: str = Field(description="modalità di trasporto")

Ciò ci consentirà di collegare gli output della chiamata LLM alla chiamata delle indicazioni.

Per questo prompt, ho scoperto che aggiungere un esempio one-shot ha davvero aiutato il modello a conformarsi all’output desiderato. Il perfezionamento di un LLM open source più piccolo per estrarre liste di punti intermedi utilizzando questi risultati da ChatGPT/PaLM potrebbe essere un interessante progetto derivato.

class MappingTemplate(object):    def __init__(self):        self.system_template = """      Sei un agente che converte dettagliati piani di viaggio in un semplice elenco di luoghi.      L'itinerario sarà segnalato da quattro hashtag. Convertilo in      un elenco di luoghi che dovrebbero visitare. Cerca di includere l'indirizzo specifico di ogni luogo.      La tua uscita dovrebbe sempre contenere il punto di partenza e di arrivo del viaggio, e può anche includere un elenco      di punti intermedi. Dovrebbe anche includere una modalità di trasporto. Il numero di punti intermedi non può superare i 20.      Se non riesci a dedurre la modalità di trasporto, fai la miglior supposizione in base alla posizione del viaggio.      Ad esempio:      ####      Itinerario per un viaggio in auto di 2 giorni a Londra:      - Giorno 1:        - Partenza da Buckingham Palace (The Mall, London SW1A 1AA)        - Visita alla Torre di Londra (Tower Hill, London EC3N 4AB)        - Esplorazione del British Museum (Great Russell St, Bloomsbury, London WC1B 3DG)        - Shopping a Oxford Street (Oxford St, London W1C 1JN)        - Fine giornata a Covent Garden (Covent Garden, London WC2E 8RF)      - Giorno 2:        - Partenza da Westminster Abbey (20 Deans Yd, Westminster, London SW1P 3PA)        - Visita Churchill War Rooms (Clive Steps, King Charles St, London SW1A 2AQ)        - Esplorazione del Museo di Storia Naturale (Cromwell Rd, Kensington, London SW7 5BD)        - Fine del viaggio al Tower Bridge (Tower Bridge Rd, London SE1 2UP)      #####      Ouput:      Partenza: Buckingham Palace, The Mall, London SW1A 1AA      Arrivo: Tower Bridge, Tower Bridge Rd, London SE1 2UP      Punti intermedi: ["Torre di Londra, Tower Hill, London EC3N 4AB", "British Museum, Great Russell St, Bloomsbury, London WC1B 3DG", "Oxford St, London W1C 1JN", "Covent Garden, London WC2E 8RF","Westminster, London SW1A 0AA", "St. James's Park, London", "Museo di Storia Naturale, Cromwell Rd, Kensington, London SW7 5BD"]      Modalità di trasporto: guida      La modalità di trasporto può essere solo una delle seguenti opzioni: "guida", "treno", "bus" o "volo".      {format_instructions}    """        self.human_template = """      ####{agent_suggestion}####    """        self.parser = PydanticOutputParser(pydantic_object=Trip)        self.system_message_prompt = SystemMessagePromptTemplate.from_template(            self.system_template,            partial_variables={                "format_instructions": self.parser.get_format_instructions()            },        )        self.human_message_prompt = HumanMessagePromptTemplate.from_template(            self.human_template, input_variables=["agent_suggestion"]        )        self.chat_prompt = ChatPromptTemplate.from_messages(            [self.system_message_prompt, self.human_message_prompt]        )

Ora, aggiungiamo un nuovo metodo alla classe Agent che può chiamare la LLM con ItineraryTemplate e MappingTemplate in sequenza utilizzando SequentialChain

def _set_up_agent_chain(self, debug=True):      # configurare LLMChain per ottenere l'itinerario come una stringa    travel_agent = LLMChain(            llm=self.chat_model,            prompt=self.itinerary_prompt.chat_prompt,            verbose=debug,            output_key="agent_suggestion",        )        # configurare LLMChain per estrarre i waypoint come un oggetto JSON    parser = LLMChain(            llm=self.chat_model,            prompt=self.mapping_prompt.chat_prompt,            output_parser=self.mapping_prompt.parser,            verbose=debug,            output_key="mapping_list",        )         # overall chain ci permette di chiamare il travel_agent e il parser in    # sequenza, con output etichettati.    overall_chain = SequentialChain(            chains=[travel_agent, parser],            input_variables=["query", "format_instructions"],            output_variables=["agent_suggestion", "mapping_list"],            verbose=debug,        )    return overall_chain

Per effettuare queste chiamate, possiamo utilizzare il seguente codice

agent_chain = travel_agent._set_up_agent_chain()mapping_prompt = MappingTemplate()agent_result = agent_chain(                {                    "query": query,                    "format_instructions": mapping_prompt.parser.get_format_instructions(),                }            )trip_suggestion = agent_result["agent_suggestion"]waypoints_dict = agent_result["mapping_list"].dict()

Gli indirizzi in waypoints_dict dovrebbero essere formattati in modo sufficiente per l’utilizzo con Google Maps, ma possono anche essere geocodificati per ridurre la probabilità di errori durante la chiamata all’API delle indicazioni. Il dizionario dei waypoint dovrebbe assomigliare a questo.

{'start': 'Berkeley, CA', 'end': 'Seattle, WA', 'waypoints': ['Redwood National and State Parks, 1111 Second St, Crescent City, CA 95531', 'Crater Lake National Park, Crater Lake National Park, OR 97604', 'Mount Rainier National Park, 55210 238th Ave E, Ashford, WA 98304', 'Olympic National Park, 3002 Mount Angeles Rd, Port Angeles, WA 98362'], 'transit': 'driving'}

6. Mettendo tutto insieme

Ora abbiamo la possibilità di utilizzare una LLM per convalidare una richiesta di viaggio, generare un itinerario dettagliato ed estrarre i waypoint come un oggetto JSON che può essere passato a valle. Vedrai che nel codice, quasi tutta questa funzionalità è gestita dalla classe Agent, che viene istanziata all’interno di TravelMapperBase e utilizzata come segue

travel_agent = Agent(   open_ai_api_key=openai_api_key,   google_palm_api_key=google_palm_api_key,   debug=verbose,)itinerary, list_of_places, validation = travel_agent.suggest_travel(query)

L’utilizzo di LangChain rende molto facile sostituire la LLM che viene utilizzata. Per PALM, è sufficiente dichiarare

from langchain.llms import GooglePalmAgent.chat_model = GooglePalm(   model_name="models/text-bison-001",   temperature=0,   google_api_key=google_palm_api_key,)

E per OpenAI, possiamo utilizzare sia ChatOpenAI che OpenAI come descritto nelle sezioni precedenti.

Ora, siamo pronti a passare alla fase successiva: come convertire l’elenco dei luoghi in un insieme di indicazioni e tracciarli su una mappa per consentire all’utente di esaminarli? Questo sarà trattato nella parte 2 di questa serie in tre parti.

Grazie per la lettura! Sentiti libero di esplorare il codice completo qui https://github.com/rmartinshort/travel_mapper. Eventuali suggerimenti per miglioramenti o estensioni delle funzionalità saranno molto apprezzati!