
Laboratorio di ricerca sulla sicurezza: riproduzione di CVE-2025-52467 (esecuzione di codice nel workflow pull_request_target di pgai / esfiltrazione di GITHUB_TOKEN) — snapshot di timescale/pgai
Artefatto di ricerca automatizzato — non è il progetto upstream.
Questo repository è un laboratorio monouso costruito da un sistema automatizzato per una tesi magistrale presso l'Université Laval sulla riproduzione di vulnerabilità pubblicate nei workflow di GitHub Actions. È uno snapshot integrale di
timescale/pgaial commit2a209b058c60823b57e8b7775b10244ff340eb8b(2025-05-14), ridistribuito sotto la licenza del progetto stesso, il cui file è incluso invariato in questo snapshot.Il progetto upstream non è coinvolto, non è mai preso di mira, e la vulnerabilità studiata qui è già pubblica. Ogni segreto e variabile in questo repository è un valore fittizio generato casualmente — nessuna credenziale reale è presente. I riferimenti alle action e le immagini dei runner sono bloccati a ciò a cui risolvevano il 2025-05-14; consulta
pinning.mdnell'output del sistema per ogni modifica apportata allo snapshot.Domande o obiezioni: [email protected]
Una libreria Python che trasforma PostgreSQL in un robusto motore di retrieval pronto per la produzione, per applicazioni RAG e Agentic.
🔄 Crea e sincronizza automaticamente gli embedding vettoriali dai dati PostgreSQL e dai documenti S3. Gli embedding si aggiornano automaticamente al variare dei dati.
🔍 Potente ricerca vettoriale e semantica con pgvector e pgvectorscale.
🛡️ Pronto per la produzione fin da subito: supporta l'elaborazione batch per una generazione efficiente degli embedding, con gestione integrata di errori del modello, limiti di frequenza e picchi di latenza.
🐘 Funziona con qualsiasi database PostgreSQL, inclusi Timescale Cloud, Amazon RDS, Supabase e altri.
Architettura di base: Il sistema è composto da un'applicazione che scrivi tu, un database PostgreSQL e worker vectorizer senza stato. L'applicazione definisce una configurazione del vectorizer per incorporare dati da fonti come PostgreSQL o S3. I worker leggono questa configurazione, elaborano la coda di dati trasformandoli in embedding e testo a chunk, e riscrivono i risultati. L'applicazione interroga quindi questi dati per alimentare RAG e la ricerca semantica.
Il punto di forza di questa architettura risiede nella sua resilienza: le modifiche ai dati apportate dall'applicazione sono disaccoppiate dal processo di embedding, garantendo che i guasti nel servizio di embedding non influiscano sulle operazioni dati principali.
Per prima cosa, installa il pacchetto pgai.``` pip install pgai
Quindi, installa i componenti del database pgai. Puoi farlo dal terminale utilizzando la CLI oppure nel codice della tua applicazione Python utilizzando il pacchetto Python pgai.```
# from the cli
pgai install -d <database-url>
# or from the python package, often done as part of your application setup
import pgai
pgai.install(DB_URL)
Questa guida rapida dimostra come pgai Vectorizer abiliti la ricerca semantica e il RAG sui dati PostgreSQL creando e sincronizzando automaticamente gli embedding man mano che i dati cambiano.
Il "segreto" fondamentale di pgai Vectorizer è il suo approccio dichiarativo alla generazione degli embedding. Definisci semplicemente la tua pipeline e lascia che Vectorizer gestisca la complessità operativa di mantenere sincronizzati gli embedding, anche quando gli endpoint di embedding non sono affidabili. Puoi definire una versione semplice della pipeline come segue:```sql CREATE TABLE IF NOT EXISTS wiki ( id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY, url TEXT NOT NULL, title TEXT NOT NULL, text TEXT NOT NULL )
SELECT ai.create_vectorizer( 'wiki'::regclass, loading => ai.loading_column(column_name=>'text'), destination => ai.destination_table(target_table=>'wiki_embedding_storage'), embedding => ai.embedding_openai(model=>'text-embedding-ada-002', dimensions=>'1536') )
Il vectorizer creerà automaticamente gli embedding per tutte le righe nella
tabella `wiki` e, cosa ancora più importante, manterrà gli embedding sincronizzati con
i dati sottostanti man mano che cambiano. **Pensalo quasi come se dichiarassi un indice** sulla
tabella `wiki`, ma invece di essere il database a gestire la struttura dati dell'indice
per te, è il Vectorizer a gestire gli embedding.
## Esecuzione della guida rapida
**Prerequisiti:**
- Un database PostgreSQL ([istruzioni per Docker](https://docs.timescale.com/self-hosted/latest/install/installation-docker/)).
- Una chiave API OpenAI (nella guida rapida usiamo openai per gli embedding, ma puoi usare [più provider](#modelli-di-embedding-supportati)).
Crea un file `.env` con il seguente contenuto:```
OPENAI_API_KEY=<your-openai-api-key>
DB_URL=<your-database-url>
Puoi scaricare il codice Python completo e il requirements.txt dall'esempio di avvio rapido ed eseguirli nella stessa directory del file .env.
Pgai richiede che alcune tabelle di catalogo e funzioni vengano installate nel database. Questa operazione viene eseguita tramite la funzione pgai.install, che installerà i componenti necessari nello schema ai del database.```python
pgai.install(DB_URL)
### Crea il vectorizer
Questo definisce il vectorizer, che indica al sistema come creare gli embedding dalla colonna `text` nella tabella `wiki`. Il vectorizer crea una vista `wiki_embedding` che possiamo interrogare per ottenere gli embedding (come vedremo di seguito).```python
async def create_vectorizer(conn: psycopg.AsyncConnection):
async with conn.cursor() as cur:
await cur.execute("""
SELECT ai.create_vectorizer(
'wiki'::regclass,
if_not_exists => true,
loading => ai.loading_column(column_name=>'text'),
embedding => ai.embedding_openai(model=>'text-embedding-ada-002', dimensions=>'1536'),
destination => ai.destination_table(view_name=>'wiki_embedding')
)
""")
await conn.commit()
In questo esempio, eseguiamo il worker di vectorizzazione una volta per creare gli embedding per i dati esistenti.```python worker = Worker(DB_URL, once=True) worker.run()
In un'applicazione reale, non chiameremmo il worker manualmente in questo modo ogni volta che vogliamo creare gli embedding. Invece, eseguiremmo il worker in background e funzionerebbe in modo continuo, interrogando il vectorizer per nuovi lavori.
Puoi eseguire il worker in background dall'applicazione, dalla CLI o da Docker. Consulta la documentazione del [vectorizer worker](https://github.com/pvharmo2/gha-lab-e8902eccd3/blob/main/docs/vectorizer/worker.md) per maggiori dettagli.
### Cerca gli articoli wiki utilizzando la ricerca semantica
Questa è una ricerca semantica pgvector standard in PostgreSQL. La ricerca viene eseguita sulla vista `wiki_embedding`, creata dal vectorizer e che include tutte le colonne della tabella `wiki` più la colonna `embedding` e il testo dei chunk. Questa funzione restituisce sia l'intera colonna `text` della tabella `wiki` sia i chunk di testo più piccoli più rilevanti per la query.```python
@dataclass
class WikiSearchResult:
id: int
url: str
title: str
text: str
chunk: str
distance: float
async def _find_relevant_chunks(client: AsyncOpenAI, query: str, limit: int = 1) -> List[WikiSearchResult]:
# Generate embedding for the query using OpenAI's API
response = await client.embeddings.create(
model="text-embedding-ada-002",
input=query,
encoding_format="float",
)
embedding = np.array(response.data[0].embedding)
# Query the database for the most similar chunks using pgvector's cosine distance operator (<=>)
async with pool.connection() as conn:
async with conn.cursor(row_factory=class_row(WikiSearchResult)) as cur:
await cur.execute("""
SELECT w.id, w.url, w.title, w.text, w.chunk, w.embedding <=> %s as distance
FROM wiki_embedding w
ORDER BY distance
LIMIT %s
""", (embedding, limit))
return await cur.fetchall()
Questo codice è notevole per ciò che non sta facendo. Si tratta di una semplice inserzione di un nuovo articolo nella tabella wiki. Non abbiamo avuto bisogno di fare nulla di diverso per creare gli embeddings: il worker vectorizer si occuperà di aggiornare gli embeddings man mano che i dati cambiano.```python
def insert_article_about_pgai(conn: psycopg.AsyncConnection):
async with conn.cursor(row_factory=class_row(WikiSearchResult)) as cur:
await cur.execute("""
INSERT INTO wiki (url, title, text) VALUES
('https://en.wikipedia.org/wiki/pgai', 'pgai', 'pgai is a Python library that turns PostgreSQL into the retrieval engine behind robust, production-ready RAG and Agentic applications. It does this by automatically creating vector embeddings for your data based on the vectorizer you define.')
""")
await conn.commit()
### Eseguire RAG con l'LLM
Questo codice esegue RAG con l'LLM. Utilizza la funzione `_find_relevant_chunks` definita in precedenza per trovare i chunk di testo più rilevanti dalla tabella `wiki` e poi usa l'LLM per generare una risposta.```python
query = "What is the main thing pgai does right now?"
relevant_chunks = await _find_relevant_chunks(client, query)
context = "\n\n".join(
f"{chunk.title}:\n{chunk.text}"
for chunk in relevant_chunks
)
prompt = f"""Question: {query}
Please use the following context to provide an accurate response:
{context}
Answer:"""
response = await client.chat.completions.create({
model: "gpt-3.5-turbo",
messages: [{ role: "user", content: prompt }],
})
print("RAG response:")
print(response.choices[0].message.content)
Cerca altre guide rapide:
Scopri di più sul vectorizer:
La nostra libreria Python pgai ti consente di lavorare con gli embedding generati dai tuoi dati:
Puoi utilizzare gli embedding vettoriali per:
Offriamo anche un'estensione PostgreSQL in grado di effettuare chiamate dirette ai modelli LLM da SQL. Questo è spesso utile per casi d'uso come classificazione, riepilogo e arricchimento dei dati sui tuoi dati esistenti.
Il vectorizer è progettato per essere flessibile e personalizzabile. Ogni vectorizer definisce una pipeline per la creazione di embedding dai tuoi dati. La pipeline è definita da una serie di componenti applicati in sequenza ai dati:
I seguenti modelli sono supportati per l'incorporamento:
Creare semplicemente embedding vettoriali è facile e diretto. La sfida è che gli LLM sono in qualche modo inaffidabili e gli endpoint mostrano guasti intermittenti e/o prestazioni degradate. Una parte critica per gestire correttamente i guasti è che le tue operazioni primarie di modifica dei dati (INSERT, UPDATE, DELETE) non dovrebbero dipendere dall'operazione di incorporamento. Altrimenti, la tua applicazione sarà inattiva ogni volta che l'endpoint è lento o fallisce e l'esperienza dell'utente ne risentirà.
Normalmente, dovresti implementare una pipeline MLops personalizzata per gestire correttamente i guasti degli endpoint. Questo comporta in genere un sistema di code come Kafka, worker specializzati e altre infrastrutture per gestire la coda e ritentare le richieste fallite. È molto lavoro ed è facile sbagliare.
Con pgai, puoi saltare tutto questo e concentrarti sulla creazione della tua applicazione perché il vectorizer gestisce gli embedding per te. Abbiamo integrato logica di accodamento e retry per gestire le varie modalità di guasto che puoi incontrare. Poiché svolgiamo questo lavoro in background, le operazioni primarie di modifica dei dati non dipendono dall'operazione di incorporamento. Questo è il motivo per cui pgai è pronto per la produzione fin da subito.
Molti database vettoriali specializzati creano embedding per te. Tuttavia, in genere falliscono quando gli endpoint di incorporamento sono inattivi o degradati, lasciando a te l'onere della gestione degli errori e dei retry.
Accogliamo con piacere i contributi a pgai! Consulta la pagina Contributing per maggiori informazioni.
pgai è ancora in una fase iniziale. Ora è un ottimo momento per contribuire a definire la direzione di questo progetto; stiamo attualmente decidendo le priorità. Dai un'occhiata all'elenco delle funzionalità a cui stiamo pensando di lavorare. Sentiti libero di commentare, ampliare l'elenco o partecipare al forum Discussions.
Per iniziare, dai un'occhiata a come contribuire e a come configurare un ambiente di sviluppo/test.
Timescale è un'azienda di database PostgreSQL. Per saperne di più visita timescale.com.
Timescale Cloud è una piattaforma cloud ad alte prestazioni, focalizzata sugli sviluppatori, che fornisce servizi PostgreSQL per i carichi di lavoro AI, time-series, analitici ed eventi più esigenti. Timescale Cloud è ideale per applicazioni di produzione e offre alta disponibilità, backup in streaming, aggiornamenti nel tempo, ruoli e permessi e un'ottima sicurezza.