Introduzione a Pydantic
Uno dei principali problemi del linguaggio di programmazione Python è la mancanza di tipizzazione statica. Python utilizza la tipizzazione dinamica, il che significa che quando si crea una variabile, non è necessario dichiararne il tipo, come in questo esempio per la variabile “X”. In linguaggi come Java o C, è invece necessario dichiarare il tipo anticipatamente. In questo articolo capiermo cos’è Pydantic e perchè dobbiamo usarlo il più possibile anche nei RAG!
#python
x = 10
#Java
int x = 10;
Un’altra caratteristica del linguaggio Python è che una volta creata una variabile, è possibile sovrascriverla con un tipo diverso da quello con cui è stata inizialmente creata. Ad esempio, se creo “X” uguale a 10, nella riga successiva posso sovrascriverla con la parola “hello” come stringa.
x = 10
x = "hello"
Questo rende più facile iniziare a utilizzare Python, ma può causare molti problemi in seguito.
Ad esempio, man mano che si costruisce un’applicazione, diventa sempre più difficile tenere traccia di tutte le variabili e del tipo che dovrebbero avere. Diventa anche complicato quando devi lavorare con funzioni in cui i tipi di argomenti non sono ovvi.
Un grande inconveniente nell’utilizzo di tipi dinamici è che si può accidentalmente creare un oggetto con valori non validi. Ad esempio, consideriamo la creazione di un oggetto “Person” con due parametri: “Nome” e “Età”, dove “Nome” dovrebbe essere una stringa e “Età” un intero. Nel primo esempio, l’oggetto viene creato correttamente con l’età impostata a 24 come intero. Tuttavia, nel secondo esempio, viene creato con l’età impostata a “24” come stringa. Inizialmente, entrambi possono sembrare funzionare correttamente, poiché Python consente questa flessibilità. Tuttavia, quando si tenta di utilizzare la variabile “età” come numero in seguito, si verificherà un errore.
alice = Person("Alice", 24)
alice = Person("Alice", "24")
Questo può essere davvero difficile da debuggare perché il fallimento potrebbe verificarsi in qualsiasi momento nel tuo programma e potrebbe essere difficile associarlo alla causa reale.
Vantaggi di Utilizzare Pydantic per la Modellazione dei Dati
Fortunatamente, Python dispone oggi di molti strumenti per risolvere questi problemi. Oggi daremo un’occhiata a Pydantic.
Pydantic è una libreria esterna che fornisce potenti strumenti per modellare i dati e risolvere tutti questi problemi di cui abbiamo appena parlato.Essenzialmente, Pydantic è una libreria di validazione dei dati in Python. È ampiamente utilizzata in vari moduli Python di rilievo, tra cui HuggingFace, FastAPI e LangChain.
I vantaggi principali di modellare i dati con Pydantic includono:
- Miglior supporto per i suggerimenti sul tipo e l’autocompletamento nell’IDE: Pydantic offre un miglior supporto per i suggerimenti sul tipo e l’autocompletamento nell’ambiente di sviluppo integrato (IDE), il che rende più facile e veloce lavorare con i tuoi dati.
- Validazione dei dati: Puoi validare i tuoi dati con Pydantic, garantendo che quando crei un oggetto, sia completamente valido e non genererà errori o problemi in seguito durante l’esecuzione del programma.
- Serializzazione in JSON: Pydantic offre un modo semplice per serializzare i tuoi oggetti in formato JSON. Questo è particolarmente utile se devi comunicare con altre applicazioni tramite Internet o se desideri semplicemente salvare i dati su disco in un formato universalmente compatibile.
Cos’è Pydantic e perchè dobbiamo usarlo nei RAG
Creare e Utilizzare Modelli Pydantic in Python
Per iniziare, assicurati di aver installato Pydantic nel tuo ambiente Python eseguendo il comando:
pip install pydantic
Per creare un modello Pydantic, inizia definendo una classe che erediti dalla classe base del modello, chiamata “BaseModel”.
All’interno di questa classe, definisci i campi del modello come variabili di classe. Ad esempio, nel seguente esempio stiamo creando un modello utente che ha tre campi: “name” che deve essere una stringa, “email”, anch’essa una stringa, e “account_id” (ID account), che sarà un intero.
from pydantic import BaseModel
class User(BaseModel):
name: str
email: str
account_id: int
Puoi creare un’istanza del modello nel seguente modo:
# Passando direttamente i dati come argomenti di parola chiave
user = User(
name="Jack",
email="jack@pixegami.io",
account_id=1234
)
Puoi anche farlo tramite lo sconfezionamento di un dizionario, il che funziona bene se hai già i dati e vuoi semplicemente inserirli nel modello. Ad esempio, se hai una risposta da un’API esterna:
user_data = {
"name": "jack",
"email": "jack@pixegami.io",
"account_id": 12345
}
user = User(**user_data)
Entrambi i modi sono validi e consentono di creare un’istanza del modello “User” con i dati specificati. Una volta creato l’oggetto “user”, è possibile accedere ai suoi attributi normalmente come mostrato negli esempi di stampa sopra.
Come si può vedere nel video sotto, programmando su VS, definendo la classe User, e iniziando a digitare un istanza della classe, si ottengono suggerimenti automatici sul tipo direttamente dal IDE.
Inotlre, passando il mouse sopra l’oggetto, l’IDE mostra quali argomenti accetta.
E ora, stampando la variabile “user”, si possono vedre tutte le informazioni contenute in questo oggetto.
Con i suggerimenti sul tipo, il codice diventa molto più gestibile poiché non è necessario ricordare tutto manualmente; l’IDE lo fa per te. Questo è particolarmente utile quando si lavora con codebase molto grandi o si collabora con altri sviluppatori.
Pydantic fornisce anche la validazione dei dati direttamente “dalla scatola”. Ciò significa che se si prova a creare un oggetto con il tipo di dati errato, fallirà immediatamente. Questo è vantaggioso perché se il software deve fallire, è meglio farlo il prima possibile, semplificando così il processo di debug.
Tornando all’esempio, se si cerca di creare un utente con un ID account che non è un intero, ad esempio se viene rappresentato come una stringa, si ottiene un errore di validazione. Questo consente di individuare immediatamente il problema, piuttosto che scoprirlo in un momento successivo, rendendo il processo di debugging più efficiente.
Cos’è Pydantic e perchè dobbiamo usarlo nei RAG:
Validazione dei Dati con Pydantic
È possibile validare anche tipi di dati più complessi. Ad esempio, supponiamo di voler validare che una stringa sia effettivamente un’email valida. Per prima cosa, modifichiamola in una stringa che non rappresenta un’email valida, ad esempio, solo “Jack”.
A questo punto, la stringa non rappresenta più un’email valida. Se provo a eseguire il codice, funzionerà ancora poiché il controllo si limita a verificare che sia una stringa. Tuttavia, posso importare un tipo di dato speciale chiamato “email string” da Pydantic e utilizzarlo al suo posto. Se lo sostituisco e eseguo nuovamente il codice si nota che ottengo un errore di validazione, indicando che la stringa non è un’email valida.
Ripristinando la stringa a un valore che rappresenta un’email valida, la validazione passerà con successo.
In questo modo, è possibile garantire che il campo email contenga sempre una stringa che rappresenta un’email valida.
Cos’è Pydantic e perchè dobbiamo usarlo nei RAG:
Aggiungere la Validazione Personalizzata con Pydantic
Se i tipi di validazione predefiniti non soddisfano le tue esigenze, puoi integrare logiche di validazione personalizzate nei tuoi modelli. Supponiamo, ad esempio, di voler garantire che tutti gli ID account siano numeri positivi, escludendo quindi i valori negativi. Per implementare questo, possiamo aggiungere del codice alla nostra classe come segue.
Prima di tutto, utilizziamo il decoratore validator
di Pydantic per creare una funzione di validazione personalizzata. Questa funzione sarà una funzione di classe e al suo interno verificheremo se il valore dell’ID account è minore o uguale a zero. Se lo è, solleveremo un ValueError
indicando che il valore non è valido. Altrimenti, restituiremo il valore. Ecco un esempio pratico di come fare:
@validator("account_id")
def validate_account_id(cls, value):
if value <= 0:
raise ValueError(f"account_id must be positive: {value}")
return value
Tornando al editor di codice per mettere in pratica quanto discusso., dopo aver importato il decoratore validator
di Pydantic, possiamo aggiungere la logica di validazione come funzione di classe nel nostro modello utente. Questo ci permette di modificare la condizione di validazione in base alle esigenze specifiche della nostra applicazione.
Cos’è Pydantic e perchè dobbiamo usarlo nei RAG:
Serializzazione JSON con Pydantic
Un’altra grande caratteristica di Pydantic è il supporto integrato per la serializzazione JSON, che rende davvero facile convertire i modelli Pydantic da o verso JSON. Per convertire un modello Pydantic in JSON, è possibile chiamare il metodo json
sull’istanza del modello. Questo restituirà una rappresentazione in formato stringa JSON dei dati del modello:
user_json_str = user.json()
print(user_json_str)
Stampando il risultato, vedrai qualcosa del genere:
{"name": "Davide", "email": "informatica@gmail.com", "account_id": 12345}
Se invece di una stringa JSON desideri un semplice oggetto dizionario Python, puoi utilizzare il metodo dict
:
user_dict = user.dict()
Se hai una stringa JSON che desideri convertire nuovamente in un modello Pydantic, puoi utilizzare il metodo parse_raw
:
json_str = '{"name": "Davide", "email": "informatica@gmail.com", "account_id": 12345}'
user = User.parse_raw(json_str)
Poiché JSON è ampiamente utilizzato e compreso in tutti i principali stack tecnologici, questa funzionalità rende davvero facile integrare il tuo codice Python con applicazioni esterne o API.