Olá, família tech! Nina Torres de volta novamente do agntbox.com. Hoje, estamos explorando algo que tem gerado buzz na comunidade de IA, especialmente para aqueles que se aventuram em criar experiências de IA mais personalizadas e cientes do contexto. Estou falando sobre LlamaIndex e, especificamente, como seu motor de consulta evoluiu para lidar com interações de dados cada vez mais complexas. Esqueça apenas jogar um PDF nele e torcer para o melhor; estamos analisando como fazê-lo realmente pensar através de múltiplas e diferentes fontes de dados.
Minha caixa de entrada, como a de muitos de vocês, tem sido inundada com perguntas sobre como ir além das configurações básicas de RAG (Geração Aumentada por Recuperação). As pessoas estão construindo aplicações incríveis, mas encontram um obstáculo quando sua IA precisa responder a perguntas que requerem a síntese de informações de um banco de dados, um conjunto de documentos e uma API ao vivo. Isso não é mais um problema simples de “encontrar este texto”. É um problema de “descobrir o que perguntar onde, e então combinar as respostas”. E, sinceramente, é um problema com o qual venho lutando em um projeto pessoal para um cliente que administra um site de e-commerce de nicho – imagine um assistente de IA que precisa verificar o estoque de produtos (banco de dados), puxar avaliações de usuários (documentos) e sugerir itens relacionados com base em preços ao vivo (API). Minha configuração inicial do LlamaIndex, embora decente para a parte das avaliações, caiu completamente no que se refere à síntese de múltiplas fontes.
Então, hoje, vamos explorar as capacidades avançadas do motor de consulta do LlamaIndex para síntese de dados de múltiplas fontes. Isso não se trata apenas de indexar diferentes tipos de dados; é sobre construir um motor de consulta que orquestra inteligentemente a recuperação de informações através dessas diversas fontes para responder a perguntas complexas e multipartes. Estamos falando de evoluir de um simples recuperador para um sistema sofisticado de roteamento e planejamento.
A Evolução de “Fazer uma Pergunta” no LlamaIndex
Lembra quando o LlamaIndex apareceu pela primeira vez? Era incrível para transformar dados não estruturados em algo com o qual um LLM poderia conversar. Você carregava documentos, construía um índice e fazia suas perguntas. Simples, eficaz. Mas a vida nem sempre é simples. Nossos dados nem sempre estão em arquivos de texto organizados. Eles estão espalhados em bancos de dados SQL, lojas noSQL, APIs e um monte de PDFs.
A abordagem inicial muitas vezes envolvia criar índices separados para cada fonte de dados. Você teria seu índice de documentos, seu índice SQL, talvez uma ferramenta de API. Então, você decidia manualmente qual consultar com base na entrada do usuário. Isso funciona para casos simples, mas e uma pergunta como, “Quais são as médias das avaliações para produtos lançados no último trimestre e algum deles tem tickets de suporte abertos?”
Essa pergunta requer:
- Consultar um banco de dados para datas de lançamento de produtos e médias de avaliações.
- Consultar outro sistema (talvez uma loja de documentos separada ou API) para tickets de suporte abertos relacionados a esses produtos.
- Sintetizar ambas as informações para fornecer uma resposta coerente.
É aqui que o LlamaIndex realmente se destacou, passando de recuperadores isolados para motores de consulta integrados que podem entender e agir em consultas tão multifacetadas.
Além da Recuperação Básica: Planejamento e Roteamento de Consultas
A mágica acontece com o que o LlamaIndex chama de “planejamento de consultas” e “roteamento”. Em vez de apenas buscar trechos de texto, o motor de consulta, frequentemente alimentado por um próprio LLM, primeiro tenta entender a intenção do usuário e depois decide a melhor estratégia para respondê-la. Isso envolve:
- Identificação de Sub-Perguntas: Decompor uma pergunta complexa em perguntas menores e independentes.
- Correspondência de Sub-Perguntas a Ferramentas/Índices: Determinar qual fonte de dados específica (por exemplo, um banco de dados SQL, um índice vetorial de documentos, um endpoint de API) é mais adequada para responder a cada sub-pergunta.
- Execução de Consultas: Executar essas sub-consultas nas ferramentas escolhidas.
- Sintetizando Resultados: Tomar as respostas individuais e combiná-las em uma única resposta abrangente.
Isso não é apenas um conceito teórico; é implementado praticamente através de coisas como o `QueryPipeline` do LlamaIndex, `RouterQueryEngine` e a capacidade de definir `Tools` personalizadas.
Preparando-se para Síntese de Múltiplas Fontes: Um Exemplo Prático
Vamos passar por uma versão simplificada do problema do meu cliente de e-commerce. Imagine que temos três fontes de dados:
- Banco de Dados de Produtos: Um banco de dados SQL com IDs de produtos, nomes, preços e datas de lançamento.
- Documentos de Avaliação: Uma coleção de avaliações de usuários (PDFs, arquivos de texto) para cada produto.
- API de Inventário: Uma API simples que retorna os níveis de estoque atuais para um dado ID de produto.
Nosso objetivo é responder a uma pergunta como: “Me fale sobre ‘Fancy Widget Pro’ – qual é o preço, o que os usuários dizem sobre ele e está atualmente em estoque?”
Etapa 1: Preparando Suas Fontes de Dados e Ferramentas
Primeiro, precisamos tornar cada fonte de dados acessível ao LlamaIndex como uma “ferramenta”.
A. Ferramenta de Banco de Dados SQL
Vamos usar o `SQLTableRetrieverTool` do LlamaIndex para isso. Supondo que você tenha um banco de dados SQLite simples chamado `products.db` com uma tabela `products`.
from llama_index.core import SQLDatabase
from sqlalchemy import create_engine, text
from llama_index.core.tools import SQLTableRetrieverTool
# Criar um banco de dados e tabela dummy para demonstração
engine = create_engine("sqlite:///products.db")
with engine.connect() as connection:
connection.execute(text("""
CREATE TABLE IF NOT EXISTS products (
product_id TEXT PRIMARY KEY,
name TEXT,
price REAL,
launch_date TEXT
);
"""))
connection.execute(text("""
INSERT OR IGNORE INTO products (product_id, name, price, launch_date) VALUES
('FWP001', 'Fancy Widget Pro', 129.99, '2025-01-15'),
('MGS002', 'Mega Gadget Super', 249.00, '2024-11-01');
"""))
connection.commit()
sql_database = SQLDatabase(engine=engine)
sql_tool = SQLTableRetrieverTool.from_instances(
sql_database=sql_database,
table_names=["products"],
description=(
"Útil para consultar informações de produtos como nome, preço e data de lançamento. "
"A entrada deve ser uma consulta SQL para a tabela 'products'."
)
)
Opinião da Nina: Este `SQLTableRetrieverTool` é um salvador. Antes dele, eu estava escrevendo funções personalizadas para interagir com bancos de dados, e parecia que eu estava reinventando a roda toda vez. Esta ferramenta torna tudo muito mais claro, embora você ainda precise ter cuidado com a engenharia de prompt para garantir que o LLM gere boas consultas SQL.
B. Ferramenta de Índice de Documentos de Avaliação
Para as avaliações, criaremos um índice vetorial a partir de alguns documentos de avaliação fictícios.
import os
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.core.tools import QueryEngineTool
# Criar um diretório e arquivos de avaliações dummy
os.makedirs("reviews", exist_ok=True)
with open("reviews/FWP001_reviews.txt", "w") as f:
f.write("Avaliações do Fancy Widget Pro:\n")
f.write("1. 'Amo absolutamente o Fancy Widget Pro! Tão rápido e confiável.' - Usuário A\n")
f.write("2. 'Um pouco caro, mas vale a pena pela qualidade.' - Usuário B\n")
f.write("3. 'Melhorou significativamente meu fluxo de trabalho.' - Usuário C\n")
with open("reviews/MGS002_reviews.txt", "w") as f:
f.write("Avaliações do Mega Gadget Super:\n")
f.write("1. 'A vida útil da bateria é incrível!' - Usuário X\n")
f.write("2. 'Processo de configuração confuso.' - Usuário Y\n")
# Carregar documentos e criar um índice
documents = SimpleDirectoryReader("reviews").load_data()
review_index = VectorStoreIndex.from_documents(documents)
review_query_engine = review_index.as_query_engine()
review_tool = QueryEngineTool(
query_engine=review_query_engine,
metadata={"name": "review_tool",
"description": "Útil para responder perguntas sobre avaliações de produtos a partir de documentos de feedback de usuários. "
"A entrada deve ser um nome ou ID de produto específico."}
)
Opinião da Nina: O `QueryEngineTool` é o seu recurso ideal para envolver qualquer motor de consulta existente do LlamaIndex em uma ferramenta. É incrivelmente flexível. Apenas certifique-se de que sua `description` seja super clara para que o LLM saiba quando usá-la.
C. Ferramenta da API de Inventário
Para a API, vamos simular uma função Python simples como uma chamada de API usando `FunctionTool`.
from llama_index.core.tools import FunctionTool
# Simular uma API de inventário
def get_stock_level(product_id: str) -> str:
"""
Retorna o nível atual de estoque para um dado ID de produto.
Args:
product_id (str): O ID do produto.
Returns:
str: Uma string indicando o nível de estoque, por exemplo, "Em Estoque", "Estoque Baixo", "Esgotado".
"""
if product_id == "FWP001":
return "Em Estoque"
elif product_id == "MGS002":
return "Estoque Baixo"
else:
return "Esgotado"
inventory_tool = FunctionTool.from_defaults(fn=get_stock_level,
description=(
"Útil para verificar o nível atual de estoque de um produto. "
"A entrada deve ser um ID de produto (por exemplo, 'FWP001')."
))
Opinião da Nina: `FunctionTool` é pura genialidade. Você pode envolver quase qualquer função Python e expô-la ao seu LLM. É assim que você se conecta a APIs reais, serviços internos ou até executa scripts locais. É uma mudança significativa para trazer ações externas nas capacidades da sua IA.
Etapa 2: Construindo o Motor de Consulta do Roteador
Agora que temos nossas ferramentas individuais, precisamos de uma maneira para o LlamaIndex escolher e usar essas ferramentas de forma inteligente. É aqui que entra o `RouterQueryEngine`. Ele usa um LLM para decidir qual ferramenta (ou sequência de ferramentas) usar com base na consulta do usuário.
from llama_index.core.query_engine import RouterQueryEngine
from llama_index.core.selectors import LLMSingleSelector
from llama_index.llms.openai import OpenAI # Supondo que você tenha a chave da API OpenAI configurada
# Inicializa o LLM (por exemplo, OpenAI) para roteamento e síntese
llm = OpenAI(model="gpt-3.5-turbo") # Ou gpt-4, depende das suas necessidades e orçamento
# Combina todas as ferramentas
all_tools = [sql_tool, review_tool, inventory_tool]
# Cria o RouterQueryEngine
router_query_engine = RouterQueryEngine(
selector=LLMSingleSelector.from_defaults(llm=llm),
query_engine_tools=all_tools,
verbose=True # Defina como True para ver as decisões de roteamento
)
A Opinião da Nina: O `LLMSingleSelector` é o padrão e muitas vezes é suficiente para indicar ao roteador qual ferramenta usar. Para cenários mais complexos, o LlamaIndex oferece outros seletores ou você pode até mesmo construir um personalizado. O `verbose=True` é absolutamente essencial durante o desenvolvimento – ele mostra o que o LLM está “pensando” ao tentar direcionar sua consulta, o que é ouro para depuração.
Passo 3: Consultando o Motor Multi-Fonte
Vamos fazer nossa pergunta complexa:
response = router_query_engine.query("Me fale sobre 'Fancy Widget Pro' – qual é seu preço, o que os usuários dizem sobre ele, e está atualmente disponível em estoque?")
print(response)
Quando você executar isso, verá a saída `verbose` mostrando o processo de pensamento do LLM:
- Ele identificará que “preço” precisa do `sql_tool`.
- “O que os usuários dizem” precisa do `review_tool`.
- “Atualmente em estoque” precisa do `inventory_tool`.
O LLM então executará cada uma dessas ferramentas, obterá suas respectivas respostas e, finalmente, sintetizará tudo em uma única resposta coerente. É como ter um mini-maestro para seus dados!
Uma saída típica pode parecer algo como:
> Selecionando ferramenta do motor de consulta: sql_tool
> Selecionando ferramenta do motor de consulta: review_tool
> Selecionando ferramenta do motor de consulta: inventory_tool
O Fancy Widget Pro (ID do produto FWP001) custa R$129,99. Os usuários geralmente adoram, descrevendo-o como "rápido e confiável" e afirmando que "melhorou muito seu fluxo de trabalho", embora alguns mencionem que é "um pouco caro". Está atualmente em estoque.
Isso é uma grande melhoria em relação a consultar manualmente cada fonte. O LLM lida com a orquestração, tornando a interação muito mais natural e poderosa.
Cenários Avançados: Pipelines de Consulta e Roteamento Recursivo
O `RouterQueryEngine` é fantástico para escolher uma única ferramenta para responder a uma sub-pergunta. Mas e se a saída de uma ferramenta precisar ser usada como entrada para outra? Ou se você precisar de uma sequência específica de operações que não pode ser tratada por uma simples seleção de uma única ferramenta?
É aqui que o `QueryPipeline` se torna incrivelmente poderoso. Ele permite encadear múltiplos componentes, incluindo ferramentas, recuperadores, LLMs e até mesmo outros motores de consulta, de forma semelhante a um grafo acíclico direcionado (DAG).
Imagine um cenário: “Encontre todos os produtos lançados nos últimos 6 meses que estão com baixo estoque e têm avaliações positivas.”
- Consultas ao banco de dados SQL para produtos lançados nos últimos 6 meses.
- Para cada ID de produto do passo 1, verifique o nível de estoque via API. Filtrar para “Baixo Estoque”.
- Para os produtos restantes, consulte documentos de avaliação para analisar o sentimento. Filtrar para “avaliações positivas”.
- Sintetizar a lista final.
Este é um processo em várias etapas e condicional. Você poderia construir um `QueryPipeline` para isso, onde a saída de um passo se torna a entrada para o próximo, possivelmente com um LLM no meio para processar resultados intermediários ou decidir o próximo passo.
Embora não iremos construir um exemplo completo de `QueryPipeline` aqui (isso é um artigo inteiro por si só!), entenda que ele oferece a flexibilidade para automação de fluxo de trabalho verdadeiramente complexa dentro da sua aplicação LlamaIndex. Você pode até incorporar um `RouterQueryEngine` dentro de um `QueryPipeline` para decisões recursivas.
Conselhos Práticos para Seu Próximo Projeto de IA
- Mapeie Suas Fontes de Dados: Antes de escrever uma única linha de código, identifique claramente todas as fontes de dados com as quais sua IA precisa interagir. Entenda sua estrutura (estruturada, não estruturada, orientada por API).
- Defina Ferramentas Claras: Para cada fonte de dados, crie uma `Tool` específica do LlamaIndex (por exemplo, `SQLTableRetrieverTool`, `QueryEngineTool`, `FunctionTool`). Crucialmente, escreva `metadata` clara e descritiva para cada ferramenta. Esta descrição é o que o LLM usa para decidir quando invocá-la. Dedique tempo a isso; é a engenharia de prompts para suas ferramentas!
- Comece com o `RouterQueryEngine`: Para projetos multi-fonte iniciais, o `RouterQueryEngine` é frequentemente o ponto de entrada mais fácil. Ele cuida da tomada de decisão baseada em LLM por você.
- Use `verbose=True` Extensivamente: Sério, esse é seu melhor amigo. Ele fornece insights sobre o raciocínio do LLM e ajuda a refinar as descrições das suas ferramentas quando o roteador toma decisões inesperadas.
- Considere o `QueryPipeline` para Fluxos de Trabalho: Se suas perguntas envolverem etapas sequenciais, lógica condicional ou onde a saída de uma ferramenta alimenta diretamente outra, comece a pensar em `QueryPipeline`. É mais complexo de configurar, mas oferece controle sem igual sobre interações de múltiplas etapas.
- Itere nas Descrições das Ferramentas: A capacidade do LLM de escolher a ferramenta certa depende muito de quão bem você descreveu o propósito e a entrada/saída esperada de cada ferramenta. Não tenha medo de experimentar diferentes redações.
A capacidade do LlamaIndex de orquestrar de forma inteligente consultas entre diferentes fontes de dados é um grande avanço para a construção de agentes verdadeiramente inteligentes. Isso nos afasta de uma lógica frágil e codificada e nos leva a sistemas que podem raciocinar sobre as necessidades de informação e buscar dados dinamicamente dos lugares mais adequados. O assistente de e-commerce do meu cliente agora é muito mais inteligente, capaz de buscar preços do banco de dados, sentimentos dos usuários a partir das avaliações e níveis de estoque via API, tudo a partir de uma única consulta em linguagem natural. É realmente algo incrível de se ver!
É isso por hoje, pessoal! Sigam em frente e construam alguns agentes de IA multi-fonte incrivelmente inteligentes. Deixem-me saber o que vocês estão construindo nos comentários!
Artigos Relacionados
- **TÍTULO: As Ferramentas CLI que Estou Amando e Por Que Você Deveria Também**
- Como Integrar Ai Sdks
- Melhores Práticas para Desenvolvimento de Agentes de IA
🕒 Published: