Navegação principal

Consegue o Postgres gerir o seu pipeline RAG?

Testámos a abordagem do pgai centrada na base de dados para perceber onde simplifica as operações RAG e onde cargas de trabalho complexas ainda exigem mais flexibilidade.

Resumo executivo

  • Os LLM só conseguem «ver» uma quantidade limitada de texto de cada vez (a janela de contexto). Isto funciona para tarefas pequenas, mas deixa de funcionar quando uma base de conhecimento abrange milhares de páginas. Mesmo quando a janela de contexto é suficiente, o desempenho pode diminuir devido ao problema de «encontrar uma agulha num palheiro».

  • O RAG («geração aumentada por recuperação») tornou-se um padrão muito comum: mantém-se uma base de conhecimento (documentos, wikis, políticas, transcrições, etc.), faz-se uma pesquisa semântica com a consulta do utilizador para recuperar os excertos mais relevantes através de embeddings e, depois, fornecem-se esses fragmentos ao LLM juntamente com a pergunta. Isto limita o contexto do modelo e, quando bem executado, pode melhorar a qualidade das respostas e reduzir as alucinações.

  • O pgai é uma extensão open source do Postgres (com ferramentas complementares) que ajuda a criar fluxos de trabalho de «recuperação com IA» sobre a base de dados open source de confiança PostgreSQL.

  • A ideia principal é transferir uma maior parte do pipeline RAG habitual para a camada da base de dados (ingerir → fragmentar → criar embeddings → manter os embeddings sincronizados), em vez de tratar a BD como «mero armazenamento» de embeddings.

  • A nossa impressão inicial é que parece promissor, mas deixa de ser adequado assim que o pipeline RAG se torna minimamente complexo, sobretudo ao nível das abordagens de fragmentação. Ainda assim, acompanharemos este projeto de perto.

O padrão RAG

Há muitas formas de criar RAG. Para uma análise mais aprofundada das diferentes abordagens, leia Exemplos práticos de soluções RAG personalizadas. O espaço de conceção torna-se surpreendentemente complexo quando a qualidade é uma prioridade, e a abordagem «predefinida» mais comum costuma ser esta:

  1. Reunir um conjunto de documentos.

  2. Dividi-los em fragmentos. Há muitos métodos para o fazer (por exemplo, por parágrafos ou agrupamentos semânticos).

  3. Converter cada fragmento num embedding.

  4. Armazenar os embeddings numa base de dados vetorial (Pinecone, Milvus, etc.) ou no Postgres através do pgvector.

  5. No momento da consulta, procurar os fragmentos mais próximos `e fornecê-los ao LLM (mais uma vez... também há muitas formas de o fazer).

Em muitas arquiteturas, os passos (1)–(3) decorrem fora da base de dados, no código da aplicação ou num pipeline de dados, e a base de dados é utilizada sobretudo para:

  • armazenar embeddings

  • pesquisar embeddings

Objetivo do pgai

O pgai é uma extensão open source do Postgres, desenvolvida pela Timescale), que procura esbater essa distinção.

Em vez de tratar os embeddings como algo que a aplicação gere manualmente, o pgai transforma-os numa funcionalidade da base de dados:

  • Define-se a tabela ou os documentos para os quais se pretende criar embeddings.

  • Especificam-se o modelo de embeddings e uma estratégia de fragmentação.

  • O pgai gere tudo o resto, incluindo a atualização dos embeddings à medida que os dados de origem mudam.

A proposta é apelativa:

  • Menos código de integração personalizado para manter.

  • Deverá ser mais fácil manter os embeddings «atualizados» à medida que os documentos de origem mudam.

  • O Postgres/pgai gere as novas tentativas, os limites de pedidos, as tarefas falhadas, etc.

Nota ao leitor: o pgai inclui o pgvector (outra extensão RAG muito popular para Postgres). O pgvector acrescenta armazenamento vetorial e pesquisa por semelhança ao Postgres, enquanto o pgai tira partido dessas funcionalidades para automatizar etapas do pipeline RAG, como a fragmentação, a criação de embeddings e a respetiva atualização.

Primeiras impressões sobre o pgai

O que nos agradou

1) É fácil pô-lo a funcionar.

O cenário ideal é bastante simples:

  • Transferir as imagens Docker da Timescale (base de dados + worker).

  • Fornecer a chave de API do fornecedor de embeddings.

  • Executar algumas instruções SQL para declarar o vetorizador (basicamente: o que converter em embeddings, como fragmentar e que modelo utilizar).

Depois disso, o pgai faz com que um worker de vetorização seja executado num processo separado e crie embeddings de forma assíncrona (por exemplo, a cada cinco minutos ou com a frequência pretendida).

2) É útil executar todo o pipeline «perto» da base de dados.

O pgai consegue ingerir conteúdos de tabelas e carregar documentos de locais como o S3, analisando-os, fragmentando-os e criando embeddings. Também processa diferentes formatos de documentos de texto, como PDF, Markdown, etc.

O que nos pareceu limitador

1) Perde-se muito controlo (e, por vezes, o RAG exige controlo).

Os sistemas RAG de elevado desempenho, quando avaliados pela qualidade das respostas, exigem muitas vezes pipelines personalizados, como:

  • regras de fragmentação personalizadas (por títulos, página, intervenções dos oradores, etc.)

  • fragmentação sensível aos metadados (preservar títulos de secções, marcas temporais, autores e tipo de documento)

  • diferentes estratégias de embeddings para cada tipo de documento

O pgai oferece menos flexibilidade nestes aspetos.

Atualmente, há duas estratégias principais de fragmentação: um divisor de texto por caracteres e um divisor recursivo de texto por caracteres, além da opção de não fragmentar. Isso poderá bastar para alguns casos de utilização, mas muitos sistemas RAG em produção exigem mais personalização.

Seria excelente se a Timescale integrasse algumas das estratégias de fragmentação mais sofisticadas presentes em bibliotecas como a Chonkie e também suportasse arquiteturas avançadas como a recuperação contextual da Anthropic.

2) Centrado no texto, não multimodal.

Muitos problemas RAG interessantes já não se limitam ao texto:

  • PDF com diagramas

  • capturas de ecrã/imagens

  • gravações de áudio

  • clipes de vídeo

Mesmo que seja possível «extrair texto» destas fontes, isso não equivale a um verdadeiro pipeline de embeddings multimodais.

Se o pgai vier a suportar modelos multimodais de ponta a ponta (carregar → fragmentar → criar embeddings para imagens, áudio e vídeo de grandes dimensões armazenados no S3, com sincronização robusta), será uma proposta convincente. Hoje, porém, é um fluxo de trabalho de embeddings de texto.

3) Se apenas precisar de embeddings, poderá não precisar do pgai.

Se o seu pipeline de ingestão já for personalizado, ou tiver de o ser, «criar embeddings de fragmentos de texto» não é a parte mais difícil do RAG. Nesse cenário, o pgai resolve a parte mais fácil do problema.

Além disso, se a base de conhecimento for atualizada com pouca frequência, a sincronização automática dos embeddings terá menos valor.

Camada de texto para SQL

Uma utilização particularmente adequada do pgai seria implementar uma interface de texto para SQL sobre as suas bases de dados. É bastante fácil fazê-lo com o módulo semantic_catalog disponibilizado pelo pgai. Basta configurar assim:

Bash

OPENAI_API_KEY="your-OpenAPI-key-goes-here"TARGET_DB="postgres://user:password@host:port/database"CATALOG_DB="postgres://user:password@host:port/database"

e fazer com que o catálogo semântico analise os dicionários de dados através de pgai semantic-catalog create. Isto gera contexto a partir do seu repositório de dados, com um aspeto semelhante a este:

Plain Text

---schema: postgres_airname: aircrafttype: tabledescription: Lists aircraft models with performance characteristics and unique codes.columns:- name: model  description: Commercial name of the aircraft model.- name: range  description: Maximum flight range in kilometers.- name: class  description: Airframe class category or configuration indicator.- name: velocity  description: Cruising speed of the aircraft.- name: code  description: Three-character aircraft code serving as the primary key....

Este contexto fica então disponível para o pgai de várias formas:

Através da pesquisa semântica:

Esta consulta devolve as tabelas, funções e outros objetos que poderão ser relevantes para a sua consulta em linguagem natural:

Bash

pgai semantic-catalog search -p "Your natural language question goes here!"

Obter o contexto em bruto:

Isto apresenta o contexto YAML em bruto relacionado com a sua consulta em linguagem natural:

Bash

pgai semantic-catalog search -p "Your natural language question goes here!" --render

Gerar SQL:

Também pode gerar diretamente o SQL em bruto necessário para responder à consulta. O contexto do passo anterior é enviado para um LLM, que gera a resposta:

Bash

pgai semantic-catalog generate-sql -p "Your natural language question goes here!"

Como pode utilizar o pgai desde já

Se estiver a criar um sistema RAG relativamente simples, vale a pena experimentar o pgai se pretender:

  • usar o Postgres como sistema de registo,

  • um mínimo de código de integração,

  • embeddings que se mantêm automaticamente sincronizados,

  • uma forma rápida de aplicar texto para SQL às suas bases de dados,

  • experimentar novas ferramentas RAG e extensões do Postgres.

Onde teríamos cautela

Provavelmente será melhor esperar antes de adotar o pgai se o seu pipeline RAG precisar de alguma das seguintes funcionalidades:

  • lógica de ingestão ou fragmentação altamente personalizada

  • muitos tipos de documentos com diferentes requisitos de análise

  • embeddings multimodais

Por último, embora seja evidente que o pgvector teve uma forte adoção, não se sabe se o pgai despertará o mesmo nível de interesse e, consequentemente, de apoio — apesar de existir há apenas cerca de 18 meses.

Gráfico do histórico de estrelas no GitHub que mostra a adoção do pgai da Timescale ao longo do tempo.

Resumo

O pgai é uma abordagem interessante ao RAG, pois permite que as bases de dados assumam uma maior parte do trabalho operacional de rotina, simplificando o código da aplicação.

Neste momento, é:

  • utilizável e verdadeiramente agradável em configurações RAG simples

  • pouco flexível para pipelines mais personalizados (sobretudo multimodais)

É promissor e merece sem dúvida ser acompanhado para vermos como evolui.

Autor

Andrew Liubinas