
Laboratório de pesquisa em segurança: reprodução do CVE-2025-52467 (execução de código no fluxo de trabalho pull_request_target do pgai / exfiltração de GITHUB_TOKEN) — snapshot de timescale/pgai
Artefacto de investigação automatizado — não é o projeto upstream.
Este repositório é um laboratório descartável construído por um harness automatizado para uma tese de mestrado na Université Laval sobre a reprodução de vulnerabilidades publicadas em workflows do GitHub Actions. É um snapshot verbatim de
timescale/pgaino commit2a209b058c60823b57e8b7775b10244ff340eb8b(2025-05-14), redistribuído sob a licença desse próprio projeto, cujo ficheiro está incluído inalterado neste snapshot.O projeto upstream não está envolvido, nunca é alvo, e a vulnerabilidade aqui estudada já é pública. Todos os segredos e variáveis neste repositório são valores fictícios gerados aleatoriamente — nenhuma credencial real está presente. As referências a ações e imagens de runners estão fixadas no que resolveram em 2025-05-14; consulte
pinning.mdna saída do harness para todas as alterações feitas ao snapshot.Perguntas ou objeções: [email protected]
Uma biblioteca Python que transforma o PostgreSQL num motor de recuperação robusto e pronto para produção para aplicações RAG e Agentic.
🔄 Crie e sincronize automaticamente embeddings vetoriais a partir de dados PostgreSQL e documentos S3. Os embeddings são atualizados automaticamente à medida que os dados mudam.
🔍 Pesquisa vetorial e semântica poderosa com pgvector e pgvectorscale.
🛡️ Pronto para produção de imediato: Suporta processamento em lote para geração eficiente de embeddings, com tratamento integrado para falhas de modelo, limites de taxa e picos de latência.
🐘 Funciona com qualquer base de dados PostgreSQL, incluindo Timescale Cloud, Amazon RDS, Supabase e mais.
Arquitetura básica: O sistema consiste numa aplicação que você escreve, numa base de dados PostgreSQL e em workers de vectorização sem estado. A aplicação define uma configuração de vectorização para incorporar dados de fontes como PostgreSQL ou S3. Os workers leem esta configuração, processam a fila de dados em embeddings e texto fragmentado, e escrevem os resultados de volta. A aplicação consulta então estes dados para alimentar RAG e pesquisa semântica.
O principal ponto forte desta arquitetura reside na sua resiliência: as modificações de dados feitas pela aplicação são desacopladas do processo de embedding, garantindo que falhas no serviço de embedding não afetam as operações de dados principais.
Primeiro, instale o pacote pgai.``` pip install pgai
Em seguida, instale os componentes de banco de dados do pgai. Você pode fazer isso pelo terminal usando a CLI ou no código da sua aplicação Python usando o pacote 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)
Este guia de início rápido demonstra como o pgai Vectorizer possibilita pesquisa semântica e RAG sobre dados do PostgreSQL, criando e sincronizando automaticamente embeddings à medida que os dados mudam.
O principal "ingrediente secreto" do pgai Vectorizer é sua abordagem declarativa para geração de embeddings. Basta definir seu pipeline e deixar o Vectorizer lidar com a complexidade operacional de manter os embeddings sincronizados, mesmo quando os endpoints de embedding não são confiáveis. Você pode definir uma versão simples do pipeline da seguinte forma:```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') )
O vectorizador criará automaticamente embeddings para todas as linhas da
tabela `wiki` e, mais importante, manterá os embeddings sincronizados com os
dados subjacentes à medida que estes mudam. **Pense nisso quase como declarar um índice** na
tabela `wiki`, mas em vez de o banco de dados gerenciar a estrutura de dados do índice
para você, o Vectorizer gerencia os embeddings.
## Executando o quick start
**Pré-requisitos:**
- Um banco de dados PostgreSQL ([instruções do docker](https://docs.timescale.com/self-hosted/latest/install/installation-docker/)).
- Uma chave de API da OpenAI (usamos openai para embedding no quick start, mas você pode usar [vários provedores](#supported-embedding-models)).
Crie um arquivo `.env` com o seguinte:```
OPENAI_API_KEY=<your-openai-api-key>
DB_URL=<your-database-url>
Podes descarregar o código Python completo e o requirements.txt do exemplo de início rápido e executá-lo no mesmo diretório do ficheiro .env.
O pgai requer algumas tabelas de catálogo e funções para serem instaladas no banco de dados. Isso é feito usando a função pgai.install, que instalará os componentes necessários no esquema ai do banco de dados.```python
pgai.install(DB_URL)
### Criar o vectorizer
Isto define o vectorizer, que indica ao sistema como criar os embeddings a partir da coluna `text` na tabela `wiki`. O vectorizer cria uma view `wiki_embedding` que podemos consultar para obter os embeddings (como veremos abaixo).```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()
Neste exemplo, executamos o worker do vectorizer uma vez para criar os embeddings para os dados existentes.```python worker = Worker(DB_URL, once=True) worker.run()
Em uma aplicação real, não chamaríamos o worker manualmente assim toda vez que quisermos criar os embeddings. Em vez disso, executaríamos o worker em segundo plano e ele rodaria continuamente, consultando por trabalho do vectorizer.
Você pode executar o worker em segundo plano a partir da aplicação, da CLI ou do Docker. Consulte a documentação do [vectorizer worker](https://github.com/pvharmo2/gha-lab-e8902eccd3/blob/main/docs/vectorizer/worker.md) para mais detalhes.
### Pesquisar os artigos da wiki usando busca semântica
Esta é a busca semântica padrão do pgvector no PostgreSQL. A busca é realizada na view `wiki_embedding`, que é criada pelo vectorizer e inclui todas as colunas da tabela `wiki` mais a coluna `embedding` e o texto do chunk. Esta função retorna tanto a coluna `text` inteira da tabela `wiki` quanto chunks menores do texto que são mais relevantes para a consulta.```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()
Este código é notável pelo que não está fazendo. Esta é uma inserção simples de um novo artigo na tabela wiki. Não precisamos fazer nada diferente para criar os embeddings, o worker do vectorizer cuidará da atualização dos embeddings conforme os dados mudam.```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()
### Executar RAG com o LLM
Este código executa RAG com o LLM. Ele usa a função `_find_relevant_chunks` definida acima para encontrar os trechos de texto mais relevantes da tabela `wiki` e, em seguida, usa o LLM para gerar uma resposta.```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)
Procure outros quickstarts:
Explore mais sobre o vectorizer:
Nossa biblioteca Python pgai permite que você trabalhe com embeddings gerados a partir dos seus dados:
Você pode usar os embeddings vetoriais para:
Também oferecemos uma extensão PostgreSQL que pode realizar chamadas de modelos LLM diretamente do SQL. Isso é frequentemente útil para casos de uso como classificação, sumarização e enriquecimento de dados em seus dados existentes.
O vectorizer foi projetado para ser flexível e personalizável. Cada vectorizer define um pipeline para criar embeddings a partir dos seus dados. O pipeline é definido por uma série de componentes que são aplicados em sequência aos dados:
Os seguintes modelos são suportados para embedding:
Simplesmente criar embeddings vetoriais é fácil e direto. O desafio é que os LLMs são um tanto imprevisíveis e os endpoints apresentam falhas intermitentes e/ou desempenho degradado. Uma parte crítica para lidar adequadamente com falhas é que suas operações primárias de modificação de dados (INSERT, UPDATE, DELETE) não devem depender da operação de embedding. Caso contrário, sua aplicação ficará fora do ar toda vez que o endpoint estiver lento ou falhar, e a experiência do usuário sofrerá.
Normalmente, você precisaria implementar um pipeline de MLops personalizado para lidar adequadamente com falhas de endpoint. Isso geralmente envolve um sistema de filas como Kafka, workers especializados e outra infraestrutura para gerenciar a fila e repetir solicitações com falha. Isso é muito trabalho e é fácil errar.
Com o pgai, você pode pular tudo isso e focar na construção da sua aplicação, porque o vectorizer está gerenciando os embeddings para você. Incorporamos lógica de fila e repetição para lidar com os vários modos de falha que você pode encontrar. Como fazemos esse trabalho em segundo plano, as operações primárias de modificação de dados não dependem da operação de embedding. É por isso que o pgai está pronto para produção desde o início.
Muitos bancos de dados vetoriais especializados criam embeddings para você. No entanto, eles normalmente falham quando os endpoints de embedding estão fora do ar ou degradados, colocando o fardo do tratamento de erros e das repetições de volta sobre você.
Aceitamos contribuições para o pgai! Consulte a página Contributing para mais informações.
O pgai ainda está em um estágio inicial. Agora é um ótimo momento para ajudar a moldar a direção deste projeto; estamos atualmente decidindo prioridades. Dê uma olhada na lista de recursos que estamos pensando em desenvolver. Sinta-se à vontade para comentar, expandir a lista ou participar do fórum Discussions.
Para começar, dê uma olhada em como contribuir e como configurar um ambiente de desenvolvimento/teste.
A Timescale é uma empresa de banco de dados PostgreSQL. Para saber mais, visite timescale.com.
O Timescale Cloud é uma plataforma em nuvem de alto desempenho, focada em desenvolvedores, que fornece serviços PostgreSQL para as cargas de trabalho mais exigentes de IA, séries temporais, análises e eventos. O Timescale Cloud é ideal para aplicações de produção e fornece alta disponibilidade, backups contínuos, atualizações ao longo do tempo, funções e permissões, e ótima segurança.