Copiloto de Pesquisa de Proteínas com Amazon Bedrock AgentCore

O gargalo que essa solução endereça

Quem trabalha com pesquisa de proteínas conhece bem o problema: varrer manualmente milhares de sequências de peptídeos em busca de candidatos estruturalmente parecidos é lento, propenso a erros e exige especialização para interpretar os resultados. A AWS publicou um guia técnico mostrando como construir um copiloto conversacional que resolve exatamente isso — o pesquisador faz uma pergunta em linguagem natural e recebe resultados ranqueados com resumo científico, tudo em uma única interface.

O que o agente é capaz de fazer

A solução reúne três capacidades dentro de um único agente conversacional:

  • Interpretação de linguagem natural: extrai parâmetros estruturados de consultas como “Encontre 10 peptídeos similares ao peptídeo LPAIVREAI do vírus da dengue”.
  • Busca por similaridade vetorial: gera embeddings de proteínas com um modelo especializado e realiza busca por cosseno em um banco de dados vetorial.
  • Sumarização científica: produz resumos dos resultados com contexto biológico e sugestões para investigação adicional.

A orquestração é feita pelo Strands Agents SDK, que coordena três ferramentas especializadas dentro de um único agente. O agente é hospedado no Amazon Bedrock AgentCore para servir em produção, e os embeddings de peptídeos ficam armazenados no Amazon Aurora PostgreSQL com a extensão pgvector.

Arquitetura da solução

Cinco componentes trabalham em conjunto para entregar a experiência conversacional:

  • Frontend Streamlit no AWS Fargate: fornece a interface de chat, envia consultas ao runtime do AgentCore e exibe os resultados em tabelas com opção de download.
  • Agente orquestrador no Bedrock AgentCore: um agente Strands rodando dentro de um runtime único do AgentCore, usando Anthropic Claude Sonnet 4.6 via Bedrock Converse API, com acesso a três ferramentas definidas pelo decorator @tool.
  • Ferramenta de parsing: um agente Strands dedicado (padrão LLM-as-parser) que extrai parâmetros estruturados — sequência, filtro de espécie, limite de resultados — a partir da consulta em linguagem natural.
  • Ferramenta de busca: gera embeddings via endpoint serverless do Amazon SageMaker AI rodando o modelo ESM-C 300M, e depois executa busca por similaridade de cosseno no Aurora PostgreSQL com pgvector.
  • Ferramenta de sumarização: outro agente Strands dedicado que analisa os resultados e produz um resumo científico conciso com sugestões de próximos passos.

Esse design de runtime único com múltiplas ferramentas mantém a implantação simples sem abrir mão da separação clara de responsabilidades. O orquestrador decide quando e como acionar cada ferramenta com base na consulta recebida.

Embeddings de proteínas com ESM-C 300M

O coração da busca por similaridade é o ESM-C 300M, um modelo de linguagem de proteínas da EvolutionaryScale que produz embeddings de 960 dimensões capturando propriedades estruturais e funcionais de sequências de aminoácidos. Dois peptídeos com função biológica parecida geram embeddings próximos no espaço vetorial, viabilizando a busca por similaridade sem necessidade de alinhamento de sequências.

O modelo é implantado como endpoint serverless do Amazon SageMaker AI, que escala para zero quando ocioso — sem custo entre invocações. Os pesos do modelo são empacotados diretamente no artefato de implantação para evitar download do HuggingFace no momento da inferência, o que é crítico para endpoints serverless onde a latência de cold start importa.

O handler de inferência constrói a arquitetura do modelo e carrega os pesos pré-empacotados:

from esm.models.esmc import ESMC
from esm.tokenization import get_esmc_model_tokenizers

def model_fn(model_dir):
    weights_path = os.path.join(model_dir, "weights", "esmc_300m.pt")
    model = ESMC(
        d_model=960,
        n_heads=15,
        n_layers=30,
        tokenizer=get_esmc_model_tokenizers(),
        use_flash_attn=False,
    )
    state_dict = torch.load(weights_path, map_location="cpu")
    model.load_state_dict(state_dict)
    model.eval()
    return model

O predict_fn recebe uma sequência de proteína, a codifica e retorna o embedding com mean pooling:

def predict_fn(input_data, model):
    sequence = input_data["sequence"]
    protein = ESMProtein(sequence=sequence)
    protein_tensor = model.encode(protein)
    logits_output = model.logits(
        protein_tensor,
        LogitsConfig(sequence=True, return_embeddings=True)
    )
    embeddings = logits_output.embeddings
    mean_embeddings = embeddings[:, 1:-1, :].mean(dim=1)
    return mean_embeddings[0].detach().cpu().tolist()

O endpoint é configurado com 6144 MB de memória, concorrência máxima de 5 e usa o container de inferência CPU PyTorch 2.6.0.

Busca vetorial com Aurora PostgreSQL e pgvector

Os embeddings ficam armazenados no Amazon Aurora PostgreSQL-Compatible Edition Serverless v2 com a extensão pgvector. O schema é direto:

CREATE TABLE peptides (
    id SERIAL PRIMARY KEY,
    sequence TEXT NOT NULL,
    embedding vector(960),
    properties JSONB,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX peptides_embedding_idx ON peptides
    USING ivfflat (embedding vector_cosine_ops)
    WITH (lists = 100);

A coluna properties do tipo JSONB guarda metadados biológicos — espécie, organismo de origem, molécula de origem, posições de epítopo — permitindo combinar filtros de vetor e metadados na mesma query. Uma consulta como “Encontre peptídeos similares a LPAIVREAI do vírus da dengue” dispara tanto a busca por similaridade de cosseno quanto um filtro em properties->>'species'.

O acesso ao banco ocorre via Amazon RDS Data API, o que significa que o runtime do agente não precisa de conectividade de rede direta com o banco — ele se comunica via HTTPS, simplificando os requisitos de rede para implantação no AgentCore.

Construindo o agente com o Strands Agents SDK

O Strands Agents SDK oferece uma abstração limpa para construir agentes que usam ferramentas. Cada ferramenta é uma função Python decorada com @tool, e o agente gera automaticamente as descrições das ferramentas para o modelo de linguagem a partir da docstring e dos type hints da função.

As três ferramentas do agente

A ferramenta de parsing delega para um agente Strands dedicado que atua como extrator de saída estruturada:

from strands import Agent, tool
from strands.models import BedrockModel

parser_agent = Agent(
    model=BedrockModel(model_id="us.anthropic.claude-sonnet-4-6", region_name="us-east-1", streaming=False),
    system_prompt="""You are a peptide query parser. Extract structured search parameters from natural language queries. Return ONLY a valid JSON object."""
)

@tool
def parse_peptide_query(query: str) -> str:
    """Parse a natural language peptide query into structured search parameters.

    Args:
        query: The user's natural language query about peptides.

    Returns:
        JSON string with extracted parameters like sequence, species, limit.
    """
    result = parser_agent(f"Parse this query: {query}")
    parsed = json.loads(str(result))
    return json.dumps(parsed)

A ferramenta de busca combina geração de embeddings via SageMaker AI com busca por similaridade no pgvector:

@tool
def search_similar_peptides(sequence: str, species: str = "", limit: int = 20) -> str:
    """Search for peptides similar to the given sequence using ESM embeddings.

    Args:
        sequence: The peptide amino acid sequence (e.g., "LPAIVREAI").
        species: Optional species filter (e.g., "Dengue virus").
        limit: Maximum number of results to return.

    Returns:
        JSON string with list of similar peptides and their properties.
    """
    # Get embedding from SageMaker AI
    resp = sagemaker_client.invoke_endpoint(
        EndpointName=endpoint,
        ContentType="application/json",
        Body=json.dumps({"sequence": sequence}))
    embedding = json.loads(resp["Body"].read().decode())["embedding"]

    # Vector similarity search with optional metadata filter
    sql = "SELECT sequence, properties, "
    sql += "(embedding <=> :query_embedding::vector) AS cosine_distance "
    sql += "FROM peptides"
    if species:
        sql += " WHERE properties->>'species' = :species"
    sql += " ORDER BY cosine_distance LIMIT :limit"

    results = run_sql(sql, params)
    return json.dumps({"results": peptides, "count": len(peptides)})

A ferramenta de sumarização usa outro agente Strands dedicado para análise científica:

summarizer_agent = Agent(
    model=BedrockModel(model_id="us.anthropic.claude-sonnet-4-6", region_name="us-east-1", streaming=False),
    system_prompt="""You are a peptide research expert providing concise, high-level summaries. Analyze search results and provide a brief, insightful summary focusing on key findings and ideas for further investigation."""
)

@tool
def summarize_results(original_query: str, search_results_json: str) -> str:
    """Summarize peptide search results with scientific insights.

    Args:
        original_query: The original user query.
        search_results_json: JSON string of search results.

    Returns:
        A concise scientific summary of the search results.
    """
    results = json.loads(search_results_json)
    summary = summarizer_agent(f"Original query: {original_query}"
                               f"Results: {results}")
    return str(summary)

O agente orquestrador

O orquestrador amarra tudo. Ele recebe a consulta do usuário e decide quais ferramentas acionar e em que ordem:

SYSTEM_PROMPT = """You are a peptide research assistant. You have three tools:
1. parse_peptide_query - Parse a natural language query into structured parameters
2. search_similar_peptides - Search for similar peptides using ESM embeddings
3. summarize_results - Summarize search results with scientific insights

For every user query, follow this workflow:
1. First, use parse_peptide_query to extract the sequence and parameters
2. Then, use search_similar_peptides with the extracted sequence
3. Finally, use summarize_results to provide insights

Always complete the three steps."""

strands_agent = Agent(
    model=BedrockModel(model_id="us.anthropic.claude-sonnet-4-6", region_name="us-east-1", streaming=False),
    tools=[parse_peptide_query, search_similar_peptides, summarize_results],
    system_prompt=SYSTEM_PROMPT
)

Vale notar o padrão “agents-as-tools” aqui: o parser e o sumarizador são eles próprios agentes Strands, mas ficam embrulhados em decorators @tool e expostos ao orquestrador como ferramentas chamáveis. O orquestrador não sabe nem precisa saber que essas ferramentas usam modelos de linguagem internamente — ele as chama como funções normais.

Implantação no Amazon Bedrock AgentCore

O Amazon Bedrock AgentCore fornece um runtime gerenciado para hospedar agentes de IA. O código do agente roda em um ambiente containerizado construído e implantado via AWS CodeBuild — sem necessidade de Docker local.

O runtime espera uma função de entrypoint que recebe um payload e um contexto:

from bedrock_agentcore.runtime import BedrockAgentCoreApp

app = BedrockAgentCoreApp()

@app.entrypoint
def invoke(payload, context):
    query = payload.get("query") or payload.get("prompt")
    result = strands_agent(query)
    return {
        "status": "success",
        "original_query": query,
        "parsed_query": _tool_outputs.get("parsed_query", {}),
        "search_results": _tool_outputs.get("search_results", []),
        "summary": _tool_outputs.get("summary", str(result)),
        "session_id": context.session_id
    }

if __name__ == '__main__':
    app.run()

A infraestrutura completa é definida como código via AWS CloudFormation. A stack de VPC cria sub-redes privadas com NAT gateways e VPC endpoints para Amazon Bedrock, RDS Data API e AWS Secrets Manager. O cluster Aurora PostgreSQL Serverless v2 é configurado com escalonamento automático de 0,5 a 4 ACUs (1–8 GB de RAM), e um recurso customizado com AWS Lambda inicializa a extensão pgvector e cria a tabela de peptídeos durante a criação da stack:

DBCluster:
  Type: AWS::RDS::DBCluster
  Properties:
    Engine: aurora-postgresql
    EnableHttpEndpoint: true  # Amazon RDS Data API
    ServerlessV2ScalingConfiguration:
      MinCapacity: 0.5
      MaxCapacity: 4

Ordem de implantação

A solução deve ser implantada nesta sequência:

  • VPC e rede: sub-redes privadas com NAT gateways e VPC endpoints para os serviços necessários.
  • Banco de dados Aurora PostgreSQL: cluster Serverless v2 com pgvector habilitado e tabela de peptídeos inicializada.
  • Endpoint do SageMaker AI: endpoint serverless rodando ESM-C 300M com 6144 MB de memória e concorrência máxima de 5.
  • Dados de peptídeos: o dataset de epítopos virais do IEDB é carregado no banco gerando embeddings para cada sequência via endpoint do SageMaker AI.
  • Runtime do AgentCore e interface Streamlit: o agente Strands é implantado no runtime do Bedrock AgentCore via AWS CodeBuild, e o frontend Streamlit é implantado no AWS Fargate.

O que considerar antes de ir para produção

  • Latência de cold start: o endpoint serverless do SageMaker AI leva 2–3 minutos na primeira invocação após um período ocioso enquanto o container inicializa e carrega os pesos. Invocações subsequentes dentro da janela de keep-alive completam em segundos. Para cargas sensíveis à latência, um endpoint provisionado é mais adequado.
  • Escolha do modelo de embedding: o ESM-C 300M foi escolhido pelo equilíbrio entre qualidade de embedding e velocidade de inferência em CPU. Para maior precisão em tarefas de similaridade estrutural, os modelos ESM-C 600M ou ESM2 oferecem dimensões maiores ao custo de mais memória e latência.
  • Escalonamento do dataset: a carga inicial usa 1.000 peptídeos amostrados do IEDB. Para datasets maiores em produção, considere carregamento em batch, aumento proporcional do parâmetro lists do índice IVFFlat e escalonamento dos ACUs do Aurora. A RDS Data API tem limite de resposta de 1 MB, então queries com grandes conjuntos de resultados podem precisar de paginação.
  • Custo: os componentes serverless (endpoint do SageMaker AI, Aurora Serverless v2, runtime do AgentCore) escalam para próximo de zero quando ociosos. Os principais custos durante uso ativo são inferência de LLM no Bedrock — três chamadas por consulta: parser, orquestrador e sumarizador — e invocações do endpoint do SageMaker AI.

O que essa arquitetura entrega na prática

O que antes exigia consultar manualmente bancos de dados de sequências, executar ferramentas de alinhamento e interpretar resultados em múltiplas aplicações — um processo que pode levar horas por busca — é reduzido a uma única consulta em linguagem natural que retorna resultados ranqueados e sumarizados em menos de um minuto (ou 2–3 minutos no cold start).

O padrão também generaliza além da pesquisa de peptídeos. Qualquer domínio onde seja necessário buscar sobre embeddings especializados, filtrar por metadados estruturados e sintetizar resultados — genômica, design de fármacos, ciência de materiais — pode se beneficiar dessa combinação de modelos de embedding específicos de domínio com orquestração por LLM.

Pré-requisitos para reproduzir a solução

  • Uma conta AWS com acesso aos modelos de fundação do Amazon Bedrock (Anthropic Claude Sonnet 4.6).
  • Python 3.12 ou superior.
  • A AWS CLI configurada com as credenciais apropriadas.
  • Permissões IAM para Amazon Bedrock, Amazon SageMaker AI, Amazon Aurora, Amazon ECS e AWS CodeBuild.
  • O pacote bedrock-agentcore-starter-toolkit instalado (pip install bedrock-agentcore-starter-toolkit).
  • O dataset de epítopos virais do IEDB.

O tempo estimado de implantação é de 30–45 minutos. Consulte as páginas de preços da AWS para Bedrock, SageMaker AI, Aurora Serverless v2 e AWS Fargate para estimativas de custo.

Limpeza dos recursos

Para evitar cobranças contínuas, exclua os recursos na ordem inversa à implantação:

  • Interface Streamlit — exclua a stack do AWS Fargate via console do AWS CloudFormation ou AWS CLI.
  • Endpoint do SageMaker AI — exclua o endpoint, a configuração do endpoint e o modelo.
  • Banco de dados — exclua o dataset IEDB e depois a stack do Aurora PostgreSQL via CloudFormation.
  • VPC — exclua a stack de VPC via CloudFormation.
  • Runtime do AgentCore — exclua o runtime via console do Amazon Bedrock AgentCore.

Referências

Vita R et al. The Immune Epitope Database (IEDB): 2024 update. Nucleic Acids Res. 2025 Jan 6;53(D1):D436-D443. doi: 10.1093/nar/gkae1092. PMID: 39558162; PMCID: PMC11701597.

ESM Team. “ESM Cambrian: Revealing the mysteries of proteins with unsupervised learning.” EvolutionaryScale, 2024. https://evolutionaryscale.ai/blog/esm-cambrian

Fonte

Build a protein research copilot with Amazon Bedrock AgentCore (https://aws.amazon.com/blogs/machine-learning/build-a-protein-research-copilot-with-amazon-bedrock-agentcore/)

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *