Nella lezione precedente, abbiamo toccato con mano l'importanza dei Prompt con il loro ruolo di trasformazione di input utente in input per LLM. In questa lezione, proseguiremo il discorso approfondendo l'importanza dei messaggi che osserveremo nella struttura interna di un oggetto di tipo ChatPromptTemplate
. Quello che succede quando creiamo un prompt in questo modo:
from langchain_core.prompts import ChatPromptTemplate
prompt_template = ChatPromptTemplate([
("system", "Sei un commesso gentile di un negozio di {tipo_negozio}"),
("user", "Cosa posso regalare ad {destinatario} di {anni} anni")
])
è ottenere un oggetto con una struttura dati interna, una lista, denominata messages
contenente i messaggi promossi dalla nostra configurazione. In particolare, la variabile system
darà vita ad un SystemMessagePromptTemplate
:
>> prompt_template.messages[0]
SystemMessagePromptTemplate(prompt=PromptTemplate(input_variables=['tipo_negozio'],..., template='Sei un commesso gentile di un negozio di {tipo_negozio}'), additional_kwargs={})
mentre user
ad uno HumanMessagePromptTemplate
:
>> prompt_template.messages[1]
HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['anni', 'destinatario'], ...., template='Cosa posso regalare ad {destinatario} di {anni} anni'), additional_kwargs={})
Si tratta in entrambi i casi di una versione customizzata di PromptTemplate
, componente già incontrata. Tutto ciò fa apparire i messaggi come un qualcosa di estremamente manipolabile tanto che, ad esempio, potremmo eseguire un'invocazione del genere:
prompt_template.messages[0].format(tipo_negozio="sport").content
ottenendo la stringa "Sei un commesso gentile di un negozio di sport".
ChatBot e dialogo continuativo con la AI tramite prompt
Ci sono contesti, come la realizzazione di ChatBot in cui si stabilisce un dialogo continuativo con la AI, in cui può essere comodo fornire i messaggi di volta in volta lasciando nella definizione del ChatPromptTemplate
una sorta di segnaposto, un MessagesPlaceholder
per l'appunto.
Vediamo un esempio. Supponiamo di richiedere un consiglio finanziario ad una A.I. (in questo esempio, abbiamo utilizzato il modello phi4 su Ollama installato in Colab):
from langchain_core.prompts import MessagesPlaceholder
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
!pip install langchain_ollama
from langchain_ollama import ChatOllama
ollama_model = ChatOllama(
model="phi4",
temperature=0.8,
max_tokens=256
)
prompt_template = ChatPromptTemplate([
("system", "Sei un consulente di investimenti molto prudente"),
MessagesPlaceholder("richiesta")
])
chain = prompt_template | ollama_model | StrOutputParser()
chain.invoke({"richiesta": [HumanMessage(content="Vorrei investire 20000 euro")]})
Come vediamo, nella definizione del ChatPromptTemplate
usiamo un MessagesPlaceholder
grazie al quale possiamo riservarci di inoltrare successivamente uno HumanMessage
creato da noi e direttamente inizializzato con la proprietà content
.
Nell'esempio chiediamo un consiglio finanziario prudente e ne riceviamo infatti uno, che non riportiamo qui per brevità, che ci invita, tra l'altro, a valutare bene il nostro profilo di rischio.
Passaggio di messaggi con MessagesPlaceholder
La configurazione mediante MessagesPlaceholder
può essere spinta ulteriormente considerando che un ChatPromptTemplate
può essere inizializzato passando direttamente noi i messaggi sfruttando il metodo from_messages
:
prompt_template = ChatPromptTemplate.from_messages([MessagesPlaceholder("richiesta")])
chain = prompt_template | ollama_model | StrOutputParser()
consiglio=chain.invoke({"richiesta": [
SystemMessage(content="Sei un consulente finanziario che ama il rischio e che consiglia spesso anche strumenti non tradizionali"),
HumanMessage(content="Vorrei investire 20000 euro")]}
)
Chiediamo con questo esempio dei consigli finanziari più spregiudicati e come vedremo la risposta del modello contemplerà azioni, cripto, commodities e molto altro.
Al di là delle proposte di investimento, quello che ci interessa notare è l'organizzazione dell'esempio. Questa volta non abbiamo affatto passato messaggi già pronti al prompt ma solo un segnaposto che viene riconosciuto con il nome richiesta.
Quando invochiamo la chain forniamo una lista di messaggi che contemplano sia la definizione del contesto sia la richiesta dell'utente e la contrassegniamo, anche in questo caso, con l'identificativo richiesta in modo che il ChatPromptTemplate
possa procedere con la corretta associazione.