Docs / Construindo um App RAG

Construindo um App RAG com aqoon

Geração Aumentada por Recuperação (RAG) é um padrão onde você recupera conteúdo relevante de uma base de conhecimento e o passa como contexto para um modelo de linguagem. O resultado é uma resposta de IA baseada nos seus próprios documentos em vez de dados de treinamento genéricos.

O aqoon é uma escolha natural para a camada de recuperação: ele armazena, processa e indexa seus documentos, e expõe uma única API de busca que faz busca híbrida semântica e por palavras-chave. Sua aplicação chama o endpoint de busca, pega os melhores resultados e os inclui no prompt que envia ao LLM.

Quer pular o tutorial e começar com um app funcional? Clone um template inicial RAG (FastAPI ou Flask) — ele inclui tudo abaixo em um projeto pronto para executar. Veja a página de SDK & Templates Iniciais.

Pré-requisitos

  • Uma conta aqoon com pelo menos uma coleção contendo documentos
  • Uma chave de API restrita com acesso concedido à coleção de destino — consulte Chaves de API & Limites de Requisições
  • Python 3.8+ (os exemplos abaixo usam o SDK aqoon mais um pacote de LLM)
  • Uma chave de API da Anthropic ou OpenAI para a etapa do LLM

Passo 1: Instalar Dependências

pip install aqoon anthropic

Se preferir OpenAI, substitua anthropic por openai — o padrão é idêntico.

Passo 2: Pesquisar no aqoon por Contexto Relevante

Instancie o cliente com sua chave de API, depois chame search(). O aqoon retorna resultados classificados — cada resultado contém o texto da passagem (content), o título do documento (title) e uma pontuação de similaridade.

from aqoon import Aqoon

AQOON_API_KEY = "aqn_your_api_key"

def search_aqoon(query: str, limit: int = 5) -> list[dict]:
    """Search aqoon and return a list of result chunks."""
    with Aqoon(api_key=AQOON_API_KEY) as client:
        response = client.search(query, limit=limit)
    return response.get("results", [])

Cada resultado na lista se parece com isso:

{
  "content": "Retrieval-Augmented Generation (RAG) combines...",
  "title": "AI Architecture Patterns.pdf",
  "document_id": "a1b2c3d4-...",
  "collection_name": "Research",
  "score": 0.91
}

Passo 3: Construir o Prompt com o Contexto Recuperado

Formate os resultados da busca como contexto e insira-os em um prompt para o LLM.

def build_prompt(query: str, chunks: list[dict]) -> str:
    """Combine retrieved chunks into a prompt."""
    if not chunks:
        return (
            f"The user asked: {query}\n\n"
            "No relevant documents were found in the knowledge base. "
            "Answer based on your general knowledge and note the absence of specific context."
        )

    context_parts = []
    for i, chunk in enumerate(chunks, start=1):
        context_parts.append(
            f"[Source {i}: {chunk['title']}]\n{chunk['content']}"
        )
    context = "\n\n---\n\n".join(context_parts)

    return (
        f"Use the following excerpts from the knowledge base to answer the question. "
        f"Cite sources by number where relevant.\n\n"
        f"{context}\n\n"
        f"Question: {query}"
    )

Passo 4: Enviar para um LLM

Passe o prompt para o Claude usando o SDK da Anthropic:

import anthropic

ANTHROPIC_API_KEY = "sk-ant-your-key"

def ask_claude(prompt: str) -> str:
    """Send a prompt to Claude and return the response text."""
    client = anthropic.Anthropic(api_key=ANTHROPIC_API_KEY)
    message = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}],
    )
    return message.content[0].text

Passo 5: Exemplo Completo Funcional

Juntando tudo:

import anthropic
from aqoon import Aqoon

AQOON_API_KEY = "aqn_your_api_key"
ANTHROPIC_API_KEY = "sk-ant-your-key"


def build_prompt(query: str, chunks: list[dict]) -> str:
    if not chunks:
        return (
            f"The user asked: {query}\n\n"
            "No relevant documents were found. Answer based on general knowledge."
        )
    context_parts = [
        f"[Source {i}: {c['title']}]\n{c['content']}"
        for i, c in enumerate(chunks, start=1)
    ]
    context = "\n\n---\n\n".join(context_parts)
    return (
        f"Use the following knowledge base excerpts to answer the question. "
        f"Cite sources by number.\n\n{context}\n\nQuestion: {query}"
    )


def rag_query(query: str) -> str:
    with Aqoon(api_key=AQOON_API_KEY) as aqoon:
        response = aqoon.search(query, limit=5)
    chunks = response.get("results", [])
    prompt = build_prompt(query, chunks)
    anthropic_client = anthropic.Anthropic(api_key=ANTHROPIC_API_KEY)
    message = anthropic_client.messages.create(
        model="claude-opus-4-5",
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}],
    )
    return message.content[0].text


if __name__ == "__main__":
    answer = rag_query("What is our policy on data retention?")
    print(answer)

Dicas

  • Escolha o escopo certo. Use uma chave de API restrita e conceda apenas as coleções relevantes para sua aplicação. Isso impede que o LLM receba contexto de documentos não relacionados.
  • Ajuste o limite de resultados. Mais resultados fornecem mais contexto ao modelo, mas aumentam o uso de tokens e o custo. De cinco a dez resultados é um bom ponto de partida; ajuste com base no comprimento típico do documento e na especificidade da consulta.
  • Trate a ausência de resultados com elegância. A função build_prompt acima mostra uma abordagem: informe ao modelo que nenhum contexto foi encontrado e deixe-o responder com conhecimento geral ou recusar a responder, dependendo do seu caso de uso.
  • Filtre por coleção. Se sua consulta é sempre limitada a um domínio, passe collection="your-collection-slug" para search() para limitar resultados a essa coleção e melhorar a relevância.
  • Cache consultas frequentes. Os resultados de busca do aqoon são determinísticos para um dado conjunto de documentos. Considere fazer cache dos resultados para consultas comuns no Redis para reduzir chamadas de API e latência.

Bônus: Exemplo JavaScript / Node.js

npm install @54startups/aqoon @anthropic-ai/sdk
import Anthropic from "@anthropic-ai/sdk";
import { Aqoon } from "@54startups/aqoon";

const AQOON_API_KEY = "aqn_your_api_key";
const ANTHROPIC_API_KEY = "sk-ant-your-key";

const aqoon = new Aqoon({ apiKey: AQOON_API_KEY });

function buildPrompt(query, chunks) {
  if (chunks.length === 0) {
    return `The user asked: ${query}\n\nNo relevant documents found.`;
  }
  const context = chunks
    .map((c, i) => `[Source ${i + 1}: ${c.title}]\n${c.content}`)
    .join("\n\n---\n\n");
  return (
    `Use the following knowledge base excerpts to answer the question. ` +
    `Cite sources by number.\n\n${context}\n\nQuestion: ${query}`
  );
}

async function ragQuery(query) {
  const response = await aqoon.search(query, { limit: 5 });
  const chunks = response.results ?? [];
  const prompt = buildPrompt(query, chunks);
  const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY });
  const message = await anthropic.messages.create({
    model: "claude-opus-4-5",
    max_tokens: 1024,
    messages: [{ role: "user", content: prompt }],
  });
  return message.content[0].text;
}

const answer = await ragQuery("What is our refund policy?");
console.log(answer);

Usando Integrações com Frameworks

Se você já está usando LangChain ou LlamaIndex, o aqoon oferece integrações de retriever de primeira classe que substituem as etapas manuais de busca e construção de prompt acima por um único objeto.

Instale os extras que você precisa junto com aqoon:

# LangChain
pip install 'aqoon[langchain]'

# LlamaIndex
pip install 'aqoon[llamaindex]'

LangChain

AqoonRetriever implementa a interface BaseRetriever do LangChain, então se encaixa diretamente em qualquer chain LCEL:

from aqoon.integrations.langchain import AqoonRetriever
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

retriever = AqoonRetriever(api_key="aqn_your_key", k=5)
llm = ChatAnthropic(model="claude-sonnet-4-20250514")

prompt = ChatPromptTemplate.from_template(
    "Answer based on this context:\n{context}\n\nQuestion: {question}"
)

chain = (
    {"context": retriever, "question": RunnablePassthrough()}
    | prompt
    | llm
    | StrOutputParser()
)

answer = chain.invoke("What is our leave policy?")

LlamaIndex

AqoonRetriever implementa a interface BaseRetriever do LlamaIndex e funciona com qualquer QueryEngine:

from aqoon.integrations.llamaindex import AqoonRetriever
from llama_index.core.query_engine import RetrieverQueryEngine

retriever = AqoonRetriever(api_key="aqn_your_key")
query_engine = RetrieverQueryEngine.from_args(retriever)
response = query_engine.query("What is our leave policy?")

Ambas as integrações cuidam da autenticação, formatação de resultados e tratamento de erros para você. Use a abordagem manual mostrada anteriormente neste tutorial quando precisar de controle refinado sobre o prompt ou a lógica de recuperação.