Repensando a pesquisa como geração de código
Evoluindo a pesquisa de serviços monolíticos para primitivas programáveis para a era dos harnesses de agentes.
A pesquisa é uma primitiva central para sistemas de IA. Modelos de fronteira tornam-se mais capazes a cada mês, mas ainda precisam de acesso a conhecimento atualizado, preciso e bem curado do mundo em geral. A pesquisa é a principal forma pela qual os sistemas de IA acessam esse conhecimento e, portanto, um componente fundamental de qualquer produto que precise tirar conclusões, realizar ações e executar trabalhos no mundo real.
Acreditamos que os pipelines de pesquisa tradicionais estão cada vez mais obsoletos na era dos agentes. A pesquisa tradicional responde a consultas, mas os agentes de hoje completam tarefas que podem assumir inúmeras formas. Essas tarefas exigem que os agentes definam estratégias de recuperação específicas da tarefa diretamente em seus harnesses. No Perplexity Computer, observamos tarefas únicas invocarem centenas ou até milhares de operações de recuperação em poucos minutos: um fluxo de trabalho que é impossível para humanos, mas absolutamente natural para agentes.
Neste mundo, a pesquisa em si deve tornar-se agentica, com seus blocos de construção acessíveis diretamente como SDKs dentro do harness do agente. Estamos introduzindo o Search as Code (SaC) como a nova arquitetura de pesquisa de referência da Perplexity.
Introdução
A pilha de pesquisa da Perplexity atende a milhares de consultas por segundo em nossas aplicações e na API Platform. Em setembro de 2025, publicamos a primeira visão geral arquitetural de nossos sistemas de pesquisa. A inovação constante dentro desses sistemas apoiou o lançamento de novas ofertas, como Search API, Agent API e Computer, com loops de autoaprimoramento otimizando a pilha de pesquisa para melhor atender aos usuários a cada dia que passa.
Tradicionalmente, sistemas de IA trataram a pesquisa como um monólito: um modelo de IA emite uma consulta, o motor de busca executa seu pipeline predefinido e o modelo consome os resultados como contexto. Em grande parte, isso funcionou bem para atender às necessidades dos primeiros usuários de IA. Dada a relativa simplicidade de suas solicitações, não havia razão para se preocupar exatamente com a forma como o pipeline de pesquisa foi projetado, ou se a arquitetura do pipeline era ideal para a tarefa em questão. Os padrões foram presumidos como bons o suficiente, assim como as interfaces padrão (chamada de função e MCPs).
No entanto, hoje essa abordagem torna-se mais obsoleta a cada mês que passa. Os usuários exigem muito mais do que análise de disparo único da IA. Eles esperam que os agentes completem tarefas de ponta a ponta ao longo de horas ou até dias. Essas tarefas podem ser complexas, abertas e altamente variáveis em suas necessidades de informação, e arquiteturas monolíticas estão cedendo sob o peso dessas demandas.
O principal gargalo é, em última análise, o de controle. Modelos de fronteira já são bastante bons em raciocinar sobre contexto fixo. No entanto, os sistemas de IA mais poderosos exigirão a capacidade de direcionar como esse contexto é recuperado, processado, agregado e renderizado para o modelo.
Sistemas de pesquisa tradicionais não foram projetados com esse grau de controlabilidade em mente. Afinal, não se pode esperar que usuários humanos exerçam controle refinado sobre os internos do pipeline de pesquisa, mesmo que fosse oferecido. Modelos de IA iniciais podem controlar a pesquisa apenas através de uma trajetória linear de chamadas de função e MCPs. Mas os modelos de fronteira de hoje, impulsionados por harnesses de agentes capazes de codificar, podem exercer controle refinado sobre quaisquer primitivas computacionais imagináveis através de código de computador. Nossa tarefa torna-se fornecer as primitivas corretas.
Para atender a essa necessidade, estamos introduzindo uma nova arquitetura de pesquisa em nossos produtos: Search as Code (SaC). Essa nova arquitetura capacita os modelos a alcançar dentro da própria pilha de pesquisa, em vez de meramente consumir seus resultados finais. A ideia central é direta: expomos os componentes da pilha de pesquisa como primitivas dentro de um SDK. Para qualquer solicitação que precise de pesquisa, um modelo monta essas primitivas sob demanda em um pipeline de recuperação adaptado a essa solicitação específica.
A montagem deste pipeline é feita através da geração e execução de código dentro de um sandbox seguro. Ao contrário de outras abordagens de pesquisa baseadas em codegen, não simplesmente inserimos uma API de pesquisa tradicional dentro de um shell ou runtime de linguagem. Em vez disso, projetamos cuidadosamente um SDK de Pesquisa Agentica que expõe os blocos de construção individuais da pesquisa no nível mais atômico possível.
Armado com esses blocos de construção, o SaC dá aos modelos controle direto sobre cada etapa individual da pesquisa: recuperação, classificação, filtragem, fanouts, renderização e muito mais. Ele também dá ao modelo acesso eficiente a estados intermediários, como listas de candidatos e sinais de classificação. Juntos, esses dois alavancas de controle e legibilidade permitem que os agentes projetem pipelines de pesquisa sob medida abrangendo milhares de operações de recuperação, otimizem esses pipelines em tempo de execução e consumam apenas as informações mais úteis como contexto do modelo.
Este artigo descreve a motivação, o design e a implementação do SaC, juntamente com resultados empíricos em benchmarks existentes e novos. O SaC estabelece uma nova fronteira de custo-desempenho para a pesquisa agentica, e estamos empolgados em compartilhá-lo com nossos usuários e a comunidade de IA mais ampla.
A Rigidez da Pesquisa Tradicional
Os primeiros motores de busca do mundo foram construídos para usuários humanos. Esses usuários passaram a esperar uma experiência previsível, geralmente consistindo em um número fixo de documentos classificados por relevância. Os usuários não queriam microgerenciar o processo de pesquisa; eles queriam inserir uma consulta e encontrar um resultado útil.
Como resultado, os motores de busca voltados para humanos convergiram para uma arquitetura monolítica comum, voltada para a produção de páginas de resultados de mecanismos de pesquisa (SERPs) amigáveis ao humano, contendo os n principais resultados para uma consulta de entrada. Esse padrão impulsionou décadas de progresso na pesquisa do consumidor. É rápido, familiar e altamente eficaz para a navegação humana.
Então vieram os LLMs, e os sistemas de IA também se tornaram consumidores de pesquisa. A Perplexity foi pioneira nessa mudança com o lançamento do nosso motor de resposta em 2022. Desde então, nossos esforços de engenharia de pesquisa concentraram-se em como otimizar o valor dos resultados de pesquisa para modelos de IA. Para construir a IA mais precisa e confiável do mundo, tivemos que projetar um sistema de pesquisa focado em tornar cada token o mais informativo possível. As inovações resultantes em recuperação de subdocumentos, eficiência de contexto, compreensão semântica e outras áreas-chave levaram a melhorias dramáticas na capacidade dos sistemas de IA de recuperar e agir com base em informações.
No entanto, mesmo os sistemas otimizados para IA herdaram em grande parte o mesmo contrato fundamental que os motores de busca tradicionais: aceitar uma consulta, executar um pipeline de pesquisa predefinido, retornar um conjunto de resultados totalmente processado. Para solicitações simples, essa abordagem funciona bem. Mas para solicitações mais complexas, isso se torna um gargalo cada vez mais limitante que degrada o desempenho, a latência e o custo.
Modos de Falha Devido à Rigidez
Pipelines de pesquisa tradicionais são projetados em torno de um único ponto de controle: os parâmetros da consulta. O motor de busca possui o restante do pipeline de acordo com sua lógica predefinida, e o modelo deve adaptar-se a ele. Para o modelo, qualquer coisa a jusante dos parâmetros da consulta é rígida—a forma da computação real está fora do controle do modelo.
Este é um limite sensato quando o consumidor é um humano verificando links. É um limite pobre quando o consumidor é um modelo de IA tentando resolver tarefas intensivas em conhecimento em um loop fechado. Em nossa experiência, essa rigidez cria três modos de falha recorrentes:
Contexto bruto. Modelos de IA são sensíveis à qualidade e compacidade do contexto. Tanto a qualidade quanto a compacidade são altamente dependentes da consulta, e pipelines de pesquisa monolíticos não são projetados para funcionar de forma otimizada em todas as consultas. Por exemplo, se um modelo precisa de uma única informação altamente cirúrgica, mas só tem acesso a um endpoint de pesquisa de ponta a ponta que prioriza o recall, usar esse endpoint introduzirá uma grande quantidade de informações irrelevantes no contexto do modelo. Por outro lado, se um modelo precisa de muitas informações, cada uma exigindo estratégias de pesquisa diferentes, ele pode ser forçado a invocar em série o mesmo pipeline subótimo para todas elas, resultando em custos crescentes e contexto ruidoso.
Falha em aproveitar o conhecimento do domínio. Em muitos casos, o modelo pode ter conhecimento do domínio (do seu treinamento, uma Skill de Agente, memória ou tokens anteriores na trajetória do LLM) que deve orientar a estratégia de pesquisa. No entanto, uma interface de pesquisa rígida impede que o modelo aproveite esse conhecimento. Por exemplo, o modelo pode perceber, para uma solicitação específica, que deve combinar sinais lexicais e semânticos de uma maneira particular, priorizar certas fontes ou agregar resultados por uma chave específica. A menos que esses insights sejam implementáveis através de parâmetros de consulta, o modelo não pode agir sobre eles.
Fluxo de controle ineficiente e poluição de contexto. Muitos fluxos de trabalho de pesquisa não são naturalmente seriais. Eles podem precisar de fan-out sobre variantes de consulta, busca paralela, deduplicação e outras operações que exigem fluxo de controle não linear e assíncrono. Forçar essas etapas através de turnos de modelo repetidos aumenta a latência e torna o fluxo de trabalho mais difícil de otimizar. Também polui o contexto do modelo com estados intermediários ruidosos que podem não ser úteis para o raciocínio do modelo, resultando em desempenho mais fraco e compactações mais frequentes.
Não havia muito o que fazer sobre esses desafios durante as eras de chamadas de função e MCP da IA. Quando cada operação de pesquisa exige seu próprio roundtrip para inferência de LLM, os desenvolvedores naturalmente preferem realizar o máximo possível nesse roundtrip. Isso significa pipelines de pesquisa de ponta a ponta que retornam conjuntos de resultados totalmente processados para consumo direto por um modelo.
Como resultado, a maioria dos sistemas de pesquisa voltados para IA ainda opera sob este contrato monolítico. No entanto, com o crescimento contínuo na inteligência do modelo e nas demandas dos usuários, as deficiências desse contrato tornam-se mais pronunciadas. Os sistemas de IA mais avançados de hoje, construídos sobre harnesses focados em código, podem compor fluxos de trabalho específicos da tarefa que executam milhares de ações a cada minuto. Os sistemas de pesquisa ainda não realizaram totalmente esse potencial.
Há muito suspeitamos que o limite certo para a pesquisa nativa de IA está mais baixo na pilha. Os modelos não deveriam meramente chamar um motor de busca. Eles deveriam ser capazes de orquestrar as peças individuais da pilha de pesquisa conforme a tarefa específica exige. Isso requer uma arquitetura fundamentalmente diferente.
Projetando uma Arquitetura de Pesquisa Programável
A próxima geração de arquiteturas de pesquisa dependerá de um princípio central: a pesquisa deve ser nativamente programável por agentes de IA. Um agente não deve ser limitado a um conjunto de pipelines de pesquisa predeterminados. Em vez disso, um agente deve ser capaz de construir o pipeline que a tarefa específica exige, usando blocos de construção componíveis projetados em diferentes níveis de abstração.
Nossa nova arquitetura Search as Code (SaC) incorpora esse princípio. No SaC, nenhuma operação de recuperação é despachada através de uma interface de chamada de função ou MCP. Todas as operações são, em vez disso, orquestradas via código Python gerado pelo modelo. Para as necessidades de pesquisa mais simples, esse código pode consistir em algumas solicitações para um endpoint de pesquisa de alto nível. Mas para tarefas complexas, o código pode ser tão intrincado quanto necessário, envolvendo execução condicional, assincronia, paralelismo e chamadas para uma ampla gama de primitivas de baixo nível.
O SaC envolve três camadas estreitamente acopladas:
Modelos servem como o plano de controle. Eles raciocinam sobre a diretiva do usuário (ou do agente pai), decompõem a diretiva em tarefas, decidem quais pipelines de recuperação e processamento são necessários para cada tarefa e geram código para implementar esses pipelines.
Sandboxes de computação fornecem computação determinística através de um runtime de execução de código seguro. Eles fornecem uma tela para que os modelos implementem fluxo de controle, processamento em lote, novas tentativas, filtragem, junção, agregação e outras operações determinísticas.
Nosso SDK de Pesquisa Agentica expõe a pilha de pesquisa da Perplexity como primitivas componíveis. Ele fornece blocos de construção desde operações de recuperação de baixo nível até análise semântica de alto nível. O SDK é incorporado dentro dos runtimes de execução dos sandboxes, permitindo que os modelos orquestrem até milhares de operações dentro de um único turno de inferência. Abaixo, discutimos nossas decisões de design para cada camada.
O SDK de Pesquisa Agentica
O SDK de Pesquisa Agentica define os blocos de construção para pesquisa programável. Importante, nosso SDK não é uma API de pesquisa preexistente empacotada como uma biblioteca. Nos últimos meses, nossa equipe de engenharia reestruturou nossa pilha de pesquisa em primitivas modulares e componíveis. Construímos o SDK de Pesquisa Agentica para fornecer acesso direto a essas primitivas, criando uma tela muito mais poderosa na qual o modelo pode orquestrar pipelines de recuperação específicos da tarefa.
Pipelines de pesquisa de alto nível, de ponta a ponta, ainda estão disponíveis dentro do SDK, mas não são mais a única opção. Em vez disso, eles servem como uma forma de abreviação para padrões de pesquisa comuns. O modelo é livre para usá-los ou ignorá-los conforme a tarefa exige.
Escolha do runtime: Consideramos Python, Rust, TypeScript e Bash como o runtime do SDK. Suspeitamos que Python seria o ajuste mais natural, dada sua ubiquidade e ecossistema de bibliotecas de processamento de dados. Testes internos confirmaram que esse é o caso, e a versão do SDK que está sendo lançada hoje é baseada em Python. Esperamos reavaliar periodicamente a escolha do runtime para garantir que ele continue a fornecer a melhor experiência de agente.
Melhoria contínua via autoresearch: Também otimizamos a consumibilidade do SDK para LLMs de fronteira através de um loop iterativo de autoresearch. Esse loop, funcionando continuamente ao longo de semanas, propõe e valida melhorias no SDK contra métricas incluindo latência, qualidade de codegen e desempenho geral da tarefa. O loop de autoresearch já fez inúmeras mudanças tanto na estrutura quanto na estética do SDK, com ganhos significativos em todas as dimensões. Planejamos refinar ainda mais o SDK via autoresearch à medida que novos modelos de fronteira e componentes de pesquisa surgirem.
Sandboxes
Sandboxes fornecem ambientes seguros para definir e executar pipelines de SaC. Eles executam código gerado pelo modelo, fornecendo acesso ao SDK de Pesquisa Agentica para facilitar a interação com primitivas de pesquisa individuais.
Fizemos investimentos significativos na otimização e endurecimento de nossos sandboxes, e o design geral do sistema merece um artigo por si só. Aqui, focamos na consideração de design mais relevante para o SaC: gerenciamento de estados intermediários.
O SaC capacita os agentes a orquestrar pipelines complexos dentro de um único turno de inferência. No entanto, certos estados intermediários precisam ser transmitidos entre turnos. Por exemplo, um modelo pode querer buscar alguns documentos no turno 1, inspecionar uma subamostra desses documentos no turno 2 para decidir o que fazer a seguir e, em seguida, desenvolver um pipeline de pesquisa a jusante para investigar ainda mais esses documentos a partir do turno 3 em diante. Como discutido acima, passar estados intermediários através do espaço de token não é uma estratégia eficaz.
Consideramos duas abordagens para gerenciar estados intermediários entre turnos:
Sistema de arquivos persistente + serde explícito: Sandboxes podem expor sistemas de arquivos persistentes para que os modelos usem entre os turnos. Os modelos que desejam persistir o estado intermediário podem incluir uma etapa de serialização dentro do código gerado para um turno, juntamente com uma etapa de desserialização dentro de um turno subsequente (seja para inspeção própria dos modelos ou para uso a jusante). A abordagem do sistema de arquivos permite que os modelos controlem direta e explicitamente como o estado intermediário é transmitido entre os turnos. Também garante rastreabilidade ao aplicar a identificação explícita e a persistência das informações usadas pelo modelo. Uma desvantagem é a latência e o overhead de contexto incorridos pela geração do código serde, embora funções utilitárias bem projetadas possam mitigar esse overhead.
REPL: Alternativamente, um sandbox pode persistir o próprio runtime de execução entre os turnos em um ambiente do tipo REPL. Isso permite que os modelos mantenham o estado intermediário na memória sem precisar serializá-lo, já que variáveis definidas ou modificadas em turnos anteriores podem simplesmente ser referenciadas por nome em turnos subsequentes. A abordagem REPL é mais eficiente em termos de token, pois evita a necessidade de gerar código serde. No entanto, a falta de uma etapa de serialização explícita pode prejudicar o desempenho a jusante por razões familiares a qualquer pessoa que tenha trabalhado com um notebook Jupyter de 100 células: à medida que o namespace das variáveis fica desordenado, torna-se mais difícil acompanhar o que precisamente é persistido entre os turnos e por quê.
Testamos ambas as abordagens e descobrimos que, embora tenham desempenho semelhante no uso comum, o serde baseado no sistema de arquivos fornece melhor confiabilidade em trajetórias particularmente longas. Portanto, adotamos o serde baseado no sistema de arquivos como nossa solução. Conjecturamos que exigir que os modelos transmitam o estado de forma declarativa, em vez de implicitamente, ajuda-os a gerenciar esse estado com mais eficácia. Esta é uma descoberta tentativa e continuaremos a iterar em ambas as abordagens.
Modelos
Os modelos que impulsionam os harnesses de agentes servem como plano de controle do SaC: montando dinamicamente pipelines de pesquisa a partir dos blocos de construção do SDK de Pesquisa Agentica para atender às necessidades de cada tarefa, e então despachando esses pipelines como código para execução no sandbox.
A Perplexity emprega uma variedade de modelos dentro de nossos harnesses de agentes, e descobrimos que os mais recentes modelos de fronteira são bastante eficazes de modo geral na geração de código de propósito geral. O principal desafio é induzir uma geração de código eficaz especificamente para o SDK de Pesquisa Agentica. Ou seja, como podemos fazer com que os modelos entrelacem efetivamente os blocos de construção do nosso SDK em pipelines otimizados para tarefas?
Ao contrário da biblioteca padrão de uma linguagem, um SDK personalizado dificilmente será representado nos dados de pré-treinamento. Mesmo com as melhorias na consumibilidade do SDK do autoresearch, muitos modelos ainda são treinados para interagir com sistemas de pesquisa através de chamadas de função e invocação direta de MCP. Esses modelos dificilmente usarão o SDK com maestria apenas com código-fonte e documentos gerados automaticamente.
Para resolver esse desafio, desenvolvemos Skills de Agente altamente sintonizadas para ensinar os modelos a aproveitar efetivamente nosso SDK. As versões iniciais foram desenvolvidas de acordo com os princípios de design da Perplexity para Skills e, em seguida, otimizadas através de um loop de autoresearch dedicado, focado nas mesmas métricas usadas na otimização do SDK. Também restringimos o tamanho da skill para evitar o inchaço do contexto, e nossas versões finais têm menos de 2000 tokens em seus arquivos SKILL.md raiz.
As Skills otimizadas vão além de listar os blocos de construção disponíveis do SDK (algo que pode ser facilmente obtido via reflexão de runtime). A maior parte dos tokens é gasta fornecendo orientação concisa e generalizável e exemplos de few-shot para compor esses blocos em padrões complexos. Armados com essas Skills, observamos modelos aproveitarem efetivamente o SDK para orquestrar pipelines de pesquisa que escalam para milhares de operações discretas.
Código como Orquestrador e Preenchedor de Lacunas
Ao combinar essas camadas, o SaC altera o relacionamento entre os modelos e a pilha de pesquisa. Em sistemas de pesquisa de pipeline fixo, o modelo situa-se acima da pesquisa e interage com ela através de uma interface de chamador serial estreita. No SaC, o modelo torna-se um participante ativo na orquestração do próprio processo de pesquisa. Todos os elementos da pilha de pesquisa tornam-se diretamente programáveis pelo modelo, com o sandbox e o SDK de Pesquisa Agentica fornecendo as interfaces necessárias para esses elementos.
Mas e quanto às capacidades que não existem nativamente? O código é um meio poderoso para orquestrar capacidades preexistentes. No entanto, o poder do código vai além da orquestração. Ele também pode servir como um preenchedor de lacunas para capacidades que não estão presentes na pilha de pesquisa ou no SDK. Os agentes se beneficiam da parcimônia, e seria ineficiente para o SDK cobrir cada operação potencial com uma função dedicada. Em vez disso, o SDK fornece as primitivas mais fundamentais, e o modelo pode construir quaisquer componentes adicionais na hora com código.
Considere, por exemplo, um regex complexo que não é implementável eficientemente via sintaxe de consulta do próprio sistema de pesquisa. Sem capacidades de codificação, o modelo seria forçado a gerar sua melhor aproximação, fazer uma consulta e realizar filtragem de espaço de token em um conjunto de resultados muito ruidoso. Com o SaC, o modelo pode, em vez disso, gerar um programa que faz chamadas paralelas ao SDK para coletar um superconjunto do conjunto de resultados do regex desejado. Após a deduplicação via SDK, o modelo pode então escrever código adicional para restringir deterministicamente os resultados ao regex exato. Dessa forma, os agentes podem implementar capacidades de pesquisa personalizadas sem inchar o SDK com sub-rotinas excessivamente específicas.
Estudo de Caso: Avisos de Fornecedores de CVE
Apresentamos um estudo de caso baseado em uma tarefa do mundo real dentro do nosso conjunto de testes. Esta tarefa pede a um agente que identifique e caracterize mais de 200 CVEs de alta gravidade de 2023–2025. Cada registro deve citar o próprio aviso do fornecedor afetado, nomear o produto e a versão de correção, e mostrar que a versão de correção está vinculada ao CVE específico.
A resposta do SaC pontuou 100% em precisão, com o uso total de tokens caindo 85,1% em relação à linha de base não-SaC (de 288,7 mil tokens para 42,9 mil tokens). Os sistemas não-Perplexity testados, discutidos com mais detalhes na Seção 4, pontuaram todos abaixo de 25%.
Apresentamos três blocos de código estilizados da trajetória para ilustrar como a programabilidade do SaC permite que o modelo implemente estratégias eficazes.
# Part 1 of 3: fan out over official advisory formats.
templates = [
("Mozilla",
'site:mozilla.org/en-US/security/advisories/mfsa{year} '
'"CVE-{year}-" "Fixed in" "Impact high"'),
("Jenkins",
'site:jenkins.io/security/advisory/{year} '
'"CVE-{year}" "Severity" "High" "Fix"'),
("Chrome",
'site:chromereleases.googleblog.com/{year} '
'"High CVE-{year}" "Stable channel has been updated"'),
("Android",
'source.android.com/docs/security/bulletin/{year}-{month:02d}-01 '
'"High" "CVE-{year}"'),
...
]
queries = [
{"vendor": vendor, "query": pattern.format(year=year, month=month)}
for year in [2023, 2024, 2025]
for vendor, pattern in templates
for month in ([1] if "{month" not in pattern else range(1, 13))
]
seed_hits = sdk.search.web_many(queries, limit_per_query=8, concurrency=12)
pages = [
{"vendor": q["vendor"], "url": h.url, "text": join_result_fields(h)}
for q, hits in zip(queries, seed_hits)
for h in hits
if official_vendor_advisory(h.url, q["vendor"])
]Este primeiro bloco é pura orquestração. O programa gerado começa codificando a regra de classe de fonte diretamente no plano de consulta: apenas formatos de aviso de propriedade do fornecedor são relevantes. Fontes que não sejam de fornecedores, incluindo NVD, MITRE, CVE Details, notícias, páginas CERT e bancos de dados de terceiros, estão estruturalmente fora do escopo. As restrições de frase exata também empurram a pesquisa para páginas cujo texto indexado já contém os detalhes precisos do CVE necessários a jusante.
# Part 2 of 3: synthesize refinements for sparse vendor-years.
coverage = summarize(pages, by=["vendor", "year", "url_kind"])
prompt = """
Goal: 230+ high or critical CVEs from official vendor advisories.
Avoid aggregators, CERTs, news, NVD, MITRE, and CVE databases.
Current coverage:
{coverage}
Suggest more site-scoped exact-phrase queries for sparse vendor-years.
Prefer per-advisory pages over archive or month-index pages.
Return JSON lines with vendor and query.
""".format(coverage=coverage)
raw = query_llm(prompt)
expanded_queries = [
row for row in parse_jsonl(raw)
if official_scope(row["query"]) and mentions_cve_year(row["query"])
]
expanded_hits = sdk.search.web_many(
unique(expanded_queries),
limit_per_query=8,
concurrency=12,
)O segundo bloco usa um LLM como uma sub-rotina de planejamento intermediário. O código resume quais pares fornecedor-ano estão produzindo páginas candidatas suficientes, solicita refinamentos direcionados e valida cada consulta proposta antes da execução. Isso preserva padrões úteis da trajetória, como sondagens de frase exata com escopo de site e backfilling adaptativo, sem codificar um crawler de aviso de CVE personalizado no SDK.
# Part 3 of 3: verify CVE-to-version binding.
all_hits = dedupe_by_url(flatten(seed_hits) + flatten(expanded_hits))
items = [
{"url": h.url, "vendor_hint": infer_vendor(h.url),
"text": join_result_fields(h)}
for h in all_hits
if official_vendor_advisory(h.url, infer_vendor(h.url))
]
verified = sdk.llm.extract_many(
items,
instruction=(
"Keep only vendor advisories where the page ties a high or critical "
"CVE to a specific fixed version, build, patch, or security level."
),
schema={
"matches": bool,
"cve": str,
"vendor": str,
"product": str,
"fix_version": str,
"severity": str,
"source_url": str,
"evidence": str,
"version_bound_to_cve": bool,
"confidence": float,
},
)
records = [
to_cve_record(x) for x in verified
if x.matches and x.version_bound_to_cve
if high_or_critical(x.severity) and x.confidence > 0.75
]
records = dedupe_by(records, key="cve")O bloco final é um verificador de resultados cuja lógica é inteiramente definida pelo agente via codegen. Embora sub-rotinas de pesquisa possam encontrar páginas de aviso plausíveis, a tarefa exige uma relação mais estrita: o aviso deve vincular um CVE a um produto afetado e uma versão de correção no texto de autoria do fornecedor. O esquema torna essa relação explícita, para que o código a jusante possa deduplicar por CVE, rejeitar URLs de agregadores, descartar evidências de versão fracas e continuar o backfilling até que o piso de contagem de registros seja atingido.
Resultados da Avaliação
Avaliamos a eficácia do SaC em um conjunto de benchmarks abrangente, focando tanto no desempenho absoluto quanto na fronteira de custo-desempenho.
Benchmarks e Sistemas
Nosso conjunto de benchmarks compreende cinco benchmarks no total, projetados para estressar fluxos de trabalho de IA dependentes de pesquisa em uma variedade de domínios, formatos de tarefa e níveis de complexidade. Usamos quatro benchmarks preexistentes: DeepSearchQA (DSQA), BrowseComp, Humanity's Last Exam (HLE) e WideSearch. Para os três primeiros benchmarks (DSQA, BrowseComp e HLE), relatamos a precisão como a métrica principal. Para WideSearch, relatamos a pontuação F1 por linha.
Também usamos o benchmark WANDR recém-desenvolvido, que se concentra em tarefas difíceis de "pesquisa ampla" que exigem orquestração cuidadosa de pesquisa, computação e raciocínio de modelo. O WANDR é inspirado nas tarefas profissionais intensivas em conhecimento que o Perplexity Computer lida para os usuários. Ele itera sobre WideSearch e benchmarks semelhantes, mas enfatiza tarefas e estruturas de tarefas mais complexas. Publicaremos o benchmark WANDR nas próximas semanas.
Avaliamos cinco sistemas baseados em agentes. Consideramos execuções individuais em vez de pontuações de "melhor de N" para isolar o desempenho da arquitetura subjacente em vez dos benefícios da paralelização. A configuração de cada sistema é descrita abaixo:
Perplexity (SaC): Avaliamos a arquitetura SaC dentro da API de Agente de produção da Perplexity. O GPT 5.5 (alto raciocínio) serve como o modelo subjacente.
OpenAI: Avaliamos a API de Respostas da OpenAI com pesquisa na web (web_search) e runtime Python (code_interpreter) habilitados. O GPT 5.5 (alto raciocínio) serve como o modelo subjacente.
Anthropic: Avaliamos os Agentes Gerenciados pela Anthropic com o conjunto de ferramentas de agente 20260401 e comandos auto-permitidos. O Opus 4.7 (alto raciocínio) serve como o modelo subjacente.
Exa: Avaliamos o Agente Exa via API de produção, com esforço definido como alto.
Parallel: Avaliamos as Tarefas Paralelas via API de produção, com o processador definido como ultra4x.
Desempenho Comparativo
A Tabela 1 relata pontuações de benchmark para cada sistema. O SaC supera todos os outros sistemas em quatro dos cinco benchmarks. No benchmark restante (HLE), o SaC está essencialmente empatado em primeiro lugar com o OpenAI Responses. A Figura 2 da Introdução visualiza essas pontuações em forma gráfica.
Benchmark | Perplexity (SaC) | OpenAI | Anthropic | Exa | Parallel |
DSQA | 0.871 | 0.733 | 0.815 | 0.530 | 0.810 |
BrowseComp | 0.805 | 0.720 | 0.598 | 0.380 | 0.560 |
HLE | 0.612 | 0.614 | 0.566 | 0.387 | 0.515 |
WideSearch | 0.651 | 0.522 | 0.590 | 0.471 | 0.584 |
WANDR | 0.386 | 0.130 | 0.152 | 0.057 | 0.126 |
Tabela 1 | Pontuações de benchmark para cada sistema avaliado. Melhor pontuação por linha em negrito.
Embora o SaC alcance desempenho de última geração em todo o conjunto de benchmarks, sua vantagem é particularmente pronunciada no WANDR. A Figura 5 detalha as pontuações do WANDR, mostrando que a implementação SaC da Perplexity supera o próximo melhor sistema por um fator de 2,5×. Apesar desta grande margem, o WANDR permanece insaturado e prova ser um desafio até mesmo para o SaC. Acreditamos que os fluxos de trabalho de pesquisa complexos e altamente horizontais exigidos pelas tarefas do WANDR exigirão avanços adicionais em pesquisa e engenharia de pesquisa para alcançar um desempenho consistentemente alto.
Finalmente, medimos os ganhos relativos do SaC versus um pipeline de pesquisa mais tradicional que aproveita a mesma infraestrutura de pesquisa da Perplexity. A Figura 6 relata a diferença nas pontuações entre as arquiteturas SaC e não-SaC em cada benchmark. De modo geral, o SaC oferece um aumento substancial no desempenho, com o maior ganho absoluto no DSQA (+19,77 pp, 29%) e o maior ganho relativo no WANDR (+12,00 pp, 45%).
Fronteira de Custo-Desempenho
Na prática, os usuários preocupam-se com o desempenho em relação ao custo. Portanto, avaliamos a fronteira de custo-desempenho no DSQA e WideSearch. Medimos o custo e o desempenho do SaC em níveis de raciocínio de modelo baixo, médio e alto, juntamente com os outros sistemas. As Figuras 7 e 8 plotam a pontuação do benchmark contra o preço por tarefa, com o eixo x invertido, de modo que pontos mais à direita sejam mais baratos e pontos mais altos representem melhor desempenho.
No DSQA, todas as três configurações de SaC situam-se na fronteira superior direita. A configuração de baixo raciocínio é mais barata que todos os outros sistemas enquanto apresenta desempenho melhor que dois deles. A configuração de raciocínio médio supera todos os sistemas não-SaC por menos de $1 por tarefa. A configuração de alto raciocínio alcança o desempenho máximo com um custo competitivo.
O WideSearch mostra uma fronteira de formato semelhante. Como no DSQA, a configuração de baixo raciocínio alcança desempenho competitivo a um custo menor do que todos os sistemas não-SaC, enquanto o raciocínio médio e alto supera os sistemas não-SaC em desempenho de tarefa.
Rumo a uma Nova Arquitetura de Computação
O Search as Code reflete uma mudança mais ampla no design de software. Por décadas, os sistemas de software foram organizados em torno de instruções determinísticas executadas por runtimes tradicionais em CPUs. Modelos de fronteira introduzem uma nova forma de computação: raciocínio de espaço de token que pode seguir e gerar instruções. Os sistemas computacionais mais capazes combinarão essas duas formas de computação em vez de escolher entre elas.
A pesquisa é um campo de prova natural para esta arquitetura híbrida. Modelos são bem adequados para decidir que evidência é necessária e como a incerteza deve ser resolvida. Runtimes determinísticos são bem adequados para processamento em lote, paralelismo, filtragem, classificação e agregação. A infraestrutura de pesquisa serve como uma camada de E/S universal, fornecendo ao runtime alças úteis nas informações do mundo que podem sustentar milhares de operações por minuto. Quando essas peças são integradas, o sistema resultante é muito mais poderoso e eficiente na realização de tarefas do mundo real.
Cada parte desta arquitetura é necessária para desbloquear essas capacidades. Sem modelos inteligentes, o sistema não pode raciocinar sobre a estratégia de pesquisa. Sem sandboxes, os modelos são forçados a E/S serial e processamento ineficiente no espaço de token. E sem uma pilha de pesquisa atomizada, o modelo não tem nada para orquestrar. O SaC funciona porque o raciocínio, a computação determinística e a E/S são projetados conjuntamente para acentuar os pontos fortes de cada camada.
Este codesign pode ser levado ainda mais longe através do desenvolvimento de loops de melhoria contínua. Por exemplo, o SDK de Pesquisa Agentica e as Skills de Agente SaC poderiam ser otimizados conjuntamente em um loop de autoresearch comum. Mais ambiciosamente, os modelos podem ser treinados para tirar proveito de primitivas de pesquisa de baixo nível expostas como um SDK. Pode-se até tentar coevoluir o design do SDK durante o próprio processo de treinamento do modelo. Esperamos buscar estratégias de codesign mais agressivas em trabalhos futuros.
Construímos o SaC para permitir que os modelos controlem o processo de pesquisa, em vez de meramente consumir seus resultados. Nossos resultados provam o poder desse controle: o SaC avança tanto o desempenho absoluto quanto a fronteira de custo-desempenho em benchmarks de agentes intensivos em conhecimento. Estamos empolgados em trazer as capacidades do SaC para nossos usuários, começando hoje com o Perplexity Computer e a API de Agente. Continuaremos a otimizar a arquitetura SaC em todas as camadas da pilha para garantir que nossos usuários (e os agentes que os atendem) tenham as capacidades de pesquisa mais poderosas e eficientes possíveis.
Citação
@online{perplexity2026RethinkingSearchAsCodeGeneration,
author = {{Perplexity} and Denis Bykov and Aleksandr Nikolenko and Artur Zayats and Maksim Gaiduk and Vitalii Polshkov and Akshay Nair and James Liounis and Kirill Priemko and Ryan Buchmayer and Phi Hoang and Jerry Ma},
title = {{Rethinking search as code generation}},
date = {2026-06-01},
url = {https://perplexity.coolkeypoint.com/hub/blog/rethinking-search-as-code-generation}
}