O problema com o RAG tradicional
Os Modelos de Linguagem de Grande Escala (LLMs) revolucionaram a forma como processamos e geramos informação, mas ainda enfrentam uma limitação importante: integrar conhecimento proveniente de múltiplas fontes ao mesmo tempo. Os métodos convencionais de Geração Aumentada por Recuperação (RAG) tratam cada documento de forma isolada, o que funciona bem para perguntas simples, mas falha quando a resposta exige conectar informações espalhadas por diferentes textos — o chamado raciocínio multi-hop.
Para endereçar essa limitação, a AWS publicou um guia técnico explorando o HippoRAG, um framework RAG que busca inspiração em como o cérebro humano organiza e recupera memórias de longo prazo.
A inspiração neurobiológica por trás do HippoRAG
O nome não é por acaso. O HippoRAG se baseia na teoria do indexamento hipocampal da memória humana. No cérebro, o neocórtex processa as entradas perceptuais enquanto o hipocampo cria um índice de associações entre memórias. Esse sistema dual permite que os seres humanos integrem informações de experiências distintas de forma eficiente.
Traduzindo isso para sistemas de IA, o HippoRAG resolve o problema do RAG tradicional por meio de três mecanismos principais:
- Construção de um Grafo de Conhecimento (GC) que representa as relações entre entidades;
- Uso do algoritmo de PageRank Personalizado (PPR) para percorrer o grafo e ranquear relevância;
- Recuperação multi-hop em uma única etapa, sem necessidade de múltiplas iterações.
Arquitetura da solução na AWS
A implementação descrita pela AWS combina quatro serviços principais:
- Amazon Bedrock: fornece as capacidades de LLM para extração de triplas do grafo de conhecimento, resposta a perguntas e identificação de entidades nomeadas;
- Amazon Neptune: armazena a estrutura do grafo de conhecimento e habilita operações básicas de grafo;
- Amazon Neptune Analytics: executa algoritmos avançados de grafo, especialmente o PageRank Personalizado para ranqueamento de relevância;
- Amazon Titan Embeddings: gera representações vetoriais do texto para correspondência por similaridade.
Pré-requisitos para implementação
Para seguir a implementação descrita no guia, são necessários:
- Uma conta AWS com acesso ao Amazon Bedrock e ao Neptune;
- Cluster do Amazon Neptune configurado e acessível;
- Grafo do Amazon Neptune Analytics criado a partir do Neptune Database;
- AWS CLI e Python 3.8+ instalados;
- Permissões de Gerenciamento de Identidade e Acesso (IAM) adequadas para: Amazon Bedrock, Amazon Neptune, Amazon Neptune Analytics e Amazon Simple Storage Service (Amazon S3).
Pipeline de processamento de dados
O primeiro passo da implementação é converter dados brutos em uma estrutura de grafo de conhecimento compatível com o Neptune. O guia utiliza o dataset HotpotQA como exemplo, percorrendo as seguintes etapas:
- Leitura do arquivo JSON de origem;
- Extração de triplas do grafo de conhecimento via Amazon Bedrock;
- Geração de arquivos CSV para carga em massa no Neptune;
- Upload dos arquivos para o Amazon S3;
- Importação para o cluster Neptune.
Configuração do importador de dados
A classe HotpotQANeptuneImporter orquestra todas as etapas da pipeline. Ela é inicializada com parâmetros de configuração do ambiente AWS, incluindo endpoints do Neptune, bucket S3, região e configurações de workers paralelos:
class HotpotQANeptuneImporter:
"""Class to handle importing HotpotQA data into Neptune."""
def __init__(
self,
hotpotqa_file_path: str,
output_dir: str,
s3_bucket: str,
s3_prefix: str,
neptune_endpoint: str,
neptune_port: int,
iam_role_arn: str,
aws_region: str,
llm_endpoint: Optional[str] = None,
embedding_endpoint: Optional[str] = None,
max_workers: int = 4,
max_examples: int = 10,
max_docs_per_example: int = 2,
use_ssl: bool = False
):
"""Initialize the importer with configuration."""
self.hotpotqa_file_path = hotpotqa_file_path
self.output_dir = output_dir
self.s3_bucket = s3_bucket
self.s3_prefix = s3_prefix
self.neptune_endpoint = neptune_endpoint
self.neptune_port = neptune_port
self.iam_role_arn = iam_role_arn
self.aws_region = aws_region
# Initialize AWS clients
self.s3_client = boto3.client('s3', region_name=aws_region)
self.session = boto3.Session()
# Initialize data structures
self.phrase_dict = {} # Maps phrase text to node ID
self.phrase_embeddings = {} # Maps phrase text to embedding vector
Extração de triplas do grafo de conhecimento
Para cada passagem de texto, o sistema usa o LLM do Bedrock para gerar triplas no formato sujeito-relação-objeto, que se tornam as arestas do grafo de conhecimento:
def extract_triples_with_llm(self, text: str) -> List[Tuple[str, str, str]]:
"""
Use an LLM to extract knowledge graph triples from text.
In this simplified version, just generate simple triples from the text.
"""
# Simple triple generation from text
words = text.split()
if len(words) < 5:
return []
# Generate simple triples from the words in the text
triples = []
for i in range(min(3, len(words) - 2)): # Get at most 3 triples
subject = words[i]
relation = "related_to"
obj = words[i+2]
triples.append((subject, relation, obj))
return triples
Conversão para CSV e carga no Neptune
Os dados são serializados em quatro arquivos CSV — phrase_nodes.csv, passage_nodes.csv, relation_edges.csv e context_edges.csv — que capturam toda a estrutura do grafo. Após o processamento, os arquivos são enviados ao S3 e importados para o Neptune via API de carga em massa, com autenticação AWS4Auth:
def import_to_neptune(self) -> Dict:
"""Import data into Neptune using the bulk loader API."""
logger.info(f"Importing data to Neptune endpoint {self.neptune_endpoint}")
loader_endpoint = f"{self.protocol}://{self.neptune_endpoint}:{self.neptune_port}/loader"
payload = {
"source": f"s3://{self.s3_bucket}/{self.s3_prefix}/",
"format": "csv",
"formatParams": {
"delimiter": ",",
"header": "true"
},
"iamRoleArn": self.iam_role_arn,
"region": self.aws_region,
"failOnError": "FALSE"
}
try:
# Create AWS4Auth for the request
credentials = self.session.get_credentials()
if credentials:
auth = AWS4Auth(
credentials.access_key,
credentials.secret_key,
self.aws_region,
'neptune-db',
session_token=credentials.token
)
response = requests.post(
loader_endpoint,
data=json.dumps(payload),
headers={"Content-Type": "application/json"},
timeout=30,
auth=auth
)
response.raise_for_status()
result = response.json()
logger.info(f"Neptune load job submitted: {result}")
return result
except Exception as e:
logger.error(f"Failed to submit Neptune load job: {e}")
raise
Implementação do HippoRAG
Configuração inicial
A configuração base do HippoRAG define o modelo LLM (Claude 3.5 Haiku via Bedrock), o modelo de embeddings (Amazon Titan Embeddings v2), a região AWS e os parâmetros de recuperação:
from src.hipporag.utils.config_utils import BaseConfig
config = BaseConfig()
config.force_index_from_scratch = True
config.openie_mode = "online"
config.llm_name = "us.anthropic.claude-3-5-haiku-20241022-v1:0"
config.embedding_model_name = "amazon.titan-embed-text-v2:0"
config.aws_region = "us-east-1"
config.save_dir = "outputs"
config.retrieval_top_k = 3
Integração com o Neptune Analytics e PageRank Personalizado
O diferencial central da implementação é o uso do Neptune Analytics para executar o PageRank personalizado. Um cliente dedicado gerencia as operações de análise avançada de grafo, recebendo nós-semente e propagando scores de relevância pelo grafo:
class NeptuneAnalyticsClient:
"""Client for Neptune Analytics operations including personalized PageRank."""
def __init__(self, graph_id, region='us-east-1'):
"""Initialize Neptune Analytics client."""
self.graph_id = graph_id
self.region = region
self.client = boto3.client('neptune-analytics', region_name=region)
logger.info(f"Initialized Neptune Analytics client for graph {graph_id}")
def run_personalized_pagerank(self, seed_nodes, damping_factor=0.85, max_iterations=20, tolerance=0.0001):
if not seed_nodes:
logger.warning("No seed nodes provided for personalized PageRank")
return []
# Format seed nodes for the query
seed_list = ",".join([f"'{node}'" for node in seed_nodes])
# Neptune Analytics personalized PageRank query using openCypher
query = f"""
CALL neptune.algo.pagerank({{
sourceNodes: [{seed_list}],
dampingFactor: {damping_factor},
maxIterations: {max_iterations},
tolerance: {tolerance},
personalized: true
}})
YIELD nodeId, score
RETURN nodeId, score
ORDER BY score DESC
LIMIT 100
"""
try:
result = self.execute_analytics_query(query)
if result and 'results' in result:
pagerank_results = [(item['nodeId'], item['score']) for item in result['results']]
logger.info(f"Personalized PageRank returned {len(pagerank_results)} results")
return pagerank_results
return []
except Exception as e:
logger.error(f"Failed to run personalized PageRank: {e}")
return []
Construção e indexação do grafo de conhecimento
O processo de indexação envolve seis etapas principais: extração de entidades nomeadas com o Claude via Bedrock, criação de triplas por extração de informação aberta, geração de embeddings com o Amazon Titan, armazenamento da estrutura no Neptune Database, adição de arestas de sinonímia entre entidades similares e preparação do grafo para processamento no Neptune Analytics.
Demonstração e resultados
O guia apresenta uma demonstração completa com perguntas reais. A inicialização do NeptuneHippoRAG recebe o endpoint do Neptune, a porta e o ID do grafo do Analytics. Em seguida, os documentos são indexados a partir do Neptune e as consultas são processadas com PageRank personalizado:
# Initialize NeptuneHippoRAG with Analytics support
hippo = NeptuneHippoRAG(
global_config=config,
neptune_endpoint="your-neptune-endpoint.us-east-1.neptune.amazonaws.com",
neptune_port=8182,
analytics_graph_id="g-your-analytics-graph-id"
)
# Index data from Neptune
hippo.index_from_neptune(limit=1000)
# Example queries
questions = [
"Who painted the Mona Lisa?",
"Which city is the capital of France?",
"What is the height of the Eiffel Tower?",
"What is the connection between Leonardo da Vinci and France?",
]
# Process each query with personalized PageRank
for question in questions:
# Get retrieval results with personalized PageRank
results = hippo.retrieve_with_personalized_pagerank([question])
# Generate answer using the QA method
qa_results, _, _ = hippo.qa(results)
# Display the answer with PageRank scores
print(f"Question: {question}")
print(f"Answer: {qa_results[0].answer}")
print(f"Top documents (PageRank ranked):")
for i, (doc, score) in enumerate(zip(results[0].docs, results[0].doc_scores)):
print(f" Doc {i+1} (Score: {score:.4f}): {doc[:100]}...")
Os resultados demonstram a capacidade do sistema de conectar informações entre documentos distintos. Para a pergunta sobre a conexão entre Leonardo da Vinci e a França, por exemplo, o HippoRAG recupera e ranqueia corretamente passagens sobre a morte do artista em território francês, seu convite pela corte do Rei Francisco I e seus últimos anos em Amboise — informações que estão em documentos separados.
Recuperação multi-hop do tipo path-finding
Uma das capacidades mais relevantes do HippoRAG é resolver perguntas do tipo path-finding — aquelas que, ao contrário das perguntas com caminho direto entre entidades, exigem explorar múltiplos caminhos possíveis no grafo. Para uma pergunta como "Qual professor de Stanford trabalha com neurociência do Alzheimer?", o algoritmo de PageRank Personalizado parte de nós-semente relacionados a "Stanford", "neurociência" e "Alzheimer" e propaga scores de relevância pelo grafo até identificar as entidades e passagens mais fortemente conectadas aos conceitos da consulta. Esse tipo de capacidade é especialmente valioso para revisão de literatura científica, análise de casos jurídicos ou diagnóstico médico.
Benefícios e considerações de performance
A abordagem HippoRAG implementada com esse conjunto de serviços AWS oferece vantagens concretas:
- Alta performance em raciocínio multi-hop: o HippoRAG se destaca como uma variante de alto desempenho do GraphRAG para tarefas complexas;
- Eficiência em etapa única: o PageRank Personalizado permite recuperação multi-hop direta, diferente de métodos iterativos;
- Analytics avançado de grafo: o Neptune Analytics entrega o algoritmo de PageRank com escalabilidade e alta performance;
- Integração nativa AWS: uso completo de serviços gerenciados como Bedrock, Neptune e Neptune Analytics para confiabilidade e facilidade operacional;
- Aprendizado contínuo: o sistema pode ser atualizado com novas informações sem necessidade de retreinamento do modelo;
- Pronto para empresas: seguro, escalável e compatível com infraestruturas AWS existentes.
Limpeza de recursos
Ao concluir os testes, é importante remover os recursos criados para evitar cobranças desnecessárias. A AWS recomenda seguir as instruções de exclusão na documentação do Amazon Neptune, Amazon Neptune Analytics, Amazon Bedrock e Amazon S3, além de remover as roles e políticas de IAM criadas durante a implementação.
Referências
- HippoRAG: Neurobiologically Inspired Long-Term Memory for Large Language Models (artigo de pesquisa original)
- Documentação do Amazon Bedrock
- Documentação do Amazon Neptune
- Documentação do Amazon Neptune Analytics
- Documentação do Amazon Titan Embeddings
Fonte
HippoRAG: Neurobiologically inspired RAG using Amazon Bedrock, Amazon Neptune, and personalized PageRank (https://aws.amazon.com/blogs/machine-learning/hipporag-neurobiologically-inspired-rag-using-amazon-bedrock-amazon-neptune-and-personalized-pagerank/)
Leave a Reply