검색을 코드 생성으로 재고하기

에이전트 하네스 시대를 위한 모놀리식 서비스에서 프로그래밍 가능한 기본 요소로의 검색 진화.

작성자Perplexity Research

검색은 AI 시스템의 핵심 기초 요소입니다. 최신 모델들은 매달 성능이 향상되고 있지만, 여전히 더 넓은 세상으로부터 최신의 정확하고 잘 선별된 지식에 접근해야 합니다. 검색은 AI 시스템이 그러한 지식을 활용하는 주요 방식이며, 따라서 결론을 도출하고 행동을 취하며 실제 작업을 수행해야 하는 모든 제품의 필수 구성 요소입니다. 우리는 에이전트 시대가 도래함에 따라 기존의 검색 파이프라인이 점점 더 구식이 되어가고 있다고 생각합니다. 기존 검색은 질의에 답변하지만, 오늘날의 에이전트는 무수한 형태로 나타날 수 있는 작업을 완료합니다. 이러한 작업을 수행하려면 에이전트가 자신의 하네스(harness) 내에서 작업별 검색 전략을 직접 정의해야 합니다. Perplexity Computer 내에서 우리는 단일 작업이 몇 분 내에 수백 또는 수천 건의 검색 작업을 호출하는 것을 목격했습니다. 이는 인간에게는 불가능하지만 에이전트에게는 지극히 자연스러운 워크플로우입니다. 이러한 환경에서 검색 자체는 에이전트화되어야 하며, 그 구성 요소는 에이전트 하네스 내에서 SDK로 직접 액세스할 수 있어야 합니다. 우리는 Perplexity의 새로운 참조 검색 아키텍처로 Search as Code (SaC)를 도입합니다.

소개

Perplexity의 검색 스택은 애플리케이션 및 API 플랫폼 전반에서 초당 수천 건의 질의를 처리합니다. 2025년 9월, 우리는 검색 시스템의 첫 번째 아키텍처 개요를 발표했습니다. 이러한 시스템 내의 지속적인 혁신은 Search API, Agent API, Computer와 같은 새로운 서비스의 출시를 뒷받침해 왔으며, 자체 개선 루프를 통해 검색 스택을 최적화하여 사용자의 편의를 매일 증대시키고 있습니다.

전통적으로 AI 시스템은 검색을 모놀리스, 즉 AI 모델이 질의를 실행하고 검색 엔진이 미리 정의된 파이프라인을 실행하며 모델이 결과를 컨텍스트로 소비하는 방식으로 처리했습니다. 대체로 이는 초기 AI 사용자의 요구 사항을 해결하는 데 잘 작동했습니다. 요청이 비교적 단순했기 때문에 검색 파이프라인이 정확히 어떻게 설계되었는지, 또는 파이프라인의 아키텍처가 당면한 작업에 최적인지 고민할 이유가 없었습니다. 기본 인터페이스(함수 호출 및 MCP)와 마찬가지로 기본 설정이면 충분하다고 간주되었습니다.

전통적인 검색 아키텍처는 모델이 순차적으로 호출하는 단일 고정 시스템을 노출하는 반면, Search as Code는 에이전트가 생성된 코드를 통해 구성하는 원자화된 검색 기본 요소를 노출합니다.

그러나 오늘날 이러한 접근 방식은 매달 더욱 구식이 되어가고 있습니다. 사용자는 AI로부터 단발적인 분석 이상의 것을 요구합니다. 그들은 에이전트가 몇 시간 또는 며칠에 걸쳐 작업을 처음부터 끝까지 완료하기를 기대합니다. 이러한 작업은 복잡하고 개방적이며 정보 요구 사항이 매우 다양할 수 있으며, 모놀리식 아키텍처는 이러한 요구의 무게를 견디지 못하고 있습니다.

핵심 병목 현상은 궁극적으로 제어의 문제입니다. 최신 모델들은 이미 고정된 컨텍스트에 대해 추론하는 능력이 상당히 뛰어납니다. 그러나 가장 강력한 AI 시스템은 해당 컨텍스트가 검색, 처리, 집계되고 모델에 렌더링되는 방식을 제어할 수 있는 능력이 필요합니다.

기존 검색 시스템은 이러한 수준의 제어 가능성을 염두에 두고 설계되지 않았습니다. 결국 인간 사용자는 설령 제공되더라도 검색 파이프라인 내부를 세밀하게 제어할 것으로 기대할 수 없습니다. 초기 AI 모델은 함수 호출과 MCP의 선형 궤적을 통해서만 검색을 제어할 수 있습니다. 그러나 코드 실행이 가능한 에이전트 하네스에 의해 구동되는 오늘날의 최신 모델은 컴퓨터 코드를 통해 상상할 수 있는 모든 계산 기본 요소를 세밀하게 제어할 수 있습니다. 우리의 과제는 올바른 기본 요소를 제공하는 것입니다.

이러한 요구를 충족하기 위해 우리는 모든 제품에 걸쳐 새로운 검색 아키텍처인 Search as Code (SaC)를 도입합니다. 이 새로운 아키텍처는 모델이 단순히 최종 출력을 소비하는 대신 검색 스택 자체에 직접 접근할 수 있도록 지원합니다. 핵심 아이디어는 간단합니다. 검색 스택의 구성 요소를 SDK 내의 기본 요소로 노출하는 것입니다. 검색이 필요한 모든 요청에 대해 모델은 이러한 기본 요소를 요청에 맞게 조정된 검색 파이프라인으로 온디맨드 방식으로 조립합니다.

이 파이프라인을 조립하는 작업은 보안 샌드박스 내에서 코드 생성 및 실행을 통해 수행됩니다. 검색에 대한 다른 코드 생성 기반 접근 방식과 달리, 우리는 단순히 기존 검색 API를 셸이나 언어 런타임 내에 삽입하지 않습니다. 대신, 우리는 검색의 개별 구성 요소를 가능한 가장 원자적인 수준에서 노출하는 에이전트 검색 SDK를 정교하게 설계했습니다.

Search as Code (SaC)는 다양한 벤치마크 제품군 전반에서 에이전트 검색의 성능 한계를 발전시킵니다.

이러한 구성 요소를 갖춘 SaC는 검색, 순위 지정, 필터링, 팬아웃, 렌더링 등 각 개별 검색 단계에 대해 모델이 직접 제어할 수 있도록 합니다. 또한 모델이 후보 목록 및 순위 지정 신호와 같은 중간 상태에 효율적으로 접근할 수 있게 합니다. 제어와 가독성이라는 이 두 가지 레버를 통해 에이전트는 수천 개의 검색 작업에 걸쳐 맞춤형 검색 파이프라인을 설계하고, 실행 중에 해당 파이프라인을 최적화하며, 가장 유용한 정보만을 모델 컨텍스트로 소비할 수 있습니다.

이 기사에서는 SaC의 동기, 설계 및 구현과 기존 벤치마크와 새로운 벤치마크에 대한 경험적 결과를 설명합니다. SaC는 에이전트 검색을 위한 새로운 비용-성능 한계를 확립하며, 이를 사용자 및 더 넓은 AI 커뮤니티와 공유하게 되어 기쁩니다.

전통적인 검색의 경직성

세계 최초의 검색 엔진은 인간 사용자를 위해 구축되었습니다. 이러한 사용자들은 일반적으로 고정된 수의 관련성 순위 문서로 구성된 예측 가능한 경험을 기대하게 되었습니다. 사용자들은 검색 과정을 세세하게 관리하고 싶어 하지 않았으며, 질의를 입력하고 유용한 결과를 찾기를 원했습니다.

결과적으로 인간 대상 검색 엔진은 입력 질의에 대해 상위 n개의 결과를 포함하는 사용자 친화적인 검색 결과 페이지(SERP)를 생성하는 공통된 모놀리식 아키텍처로 수렴했습니다. 이 패턴은 소비자 검색 분야에서 수십 년간의 발전을 이끌었습니다. 이는 빠르고 친숙하며 인간의 브라우징에 매우 효과적입니다.

그 후 LLM이 등장하면서 AI 시스템도 검색의 소비자가 되었습니다. Perplexity는 2022년 답변 엔진을 출시하며 이러한 전환을 주도했습니다. 그 이후로 우리의 검색 엔지니어링 노력은 AI 모델을 위한 검색 결과의 가치를 최적화하는 방법에 집중되었습니다. 세계에서 가장 정확하고 신뢰할 수 있는 AI를 구축하기 위해 우리는 각 토큰을 가능한 한 정보가 밀집되도록 만드는 데 중점을 둔 검색 시스템을 설계해야 했습니다. 하위 문서 검색, 컨텍스트 효율성, 의미론적 이해 및 기타 주요 영역에서의 혁신적인 결과는 AI 시스템이 정보를 검색하고 행동하는 능력의 극적인 향상을 이끌었습니다.

그러나 AI 최적화 시스템조차도 전통적인 검색 엔진과 동일한 기본 계약(질의 수락, 미리 정의된 검색 파이프라인 실행, 완전히 처리된 결과 집합 반환)을 상당 부분 상속받았습니다. 단순한 요청의 경우 이 접근 방식이 잘 작동합니다. 그러나 더 복잡한 요청의 경우, 이는 성능, 대기 시간 및 비용을 저하시키는 점점 더 제한적인 병목 현상이 됩니다.

전통적인 검색 시스템은 에이전트 워크플로우가 모델이 볼 수 있는 턴을 통해 검색을 순차적으로 수행하도록 강제합니다. 모델은 서로 다른 질의 매개변수에 대해 동일한 검색 파이프라인을 반복적으로 호출하고 모든 결과를 모델 컨텍스트에 도입해야 합니다.

경직성으로 인한 실패 모드

전통적인 검색 파이프라인은 질의 매개변수라는 단일 제어 지점을 중심으로 설계되었습니다. 검색 엔진은 미리 정의된 로직에 따라 파이프라인의 나머지 부분을 소유하며, 모델은 이에 적응해야 합니다. 모델 입장에서 질의 매개변수의 하위는 무엇이든 경직되어 있으며, 실제 계산 형태는 모델의 제어 범위를 벗어납니다.

이는 소비자가 링크를 스캔하는 인간일 때는 합리적인 경계입니다. 그러나 소비자가 폐루프에서 지식 집약적인 작업을 해결하려는 AI 모델일 때는 좋지 않은 경계입니다. 우리의 경험에 따르면 이러한 경직성은 세 가지 반복적인 실패 모드를 생성합니다.

조악한 컨텍스트. AI 모델은 컨텍스트의 품질과 간결성에 민감합니다. 품질과 간결성 모두 질의에 크게 의존하며, 모놀리식 검색 파이프라인은 모든 질의에서 최적으로 수행되도록 설계되지 않았습니다. 예를 들어, 모델이 매우 정밀한 정보 하나를 필요로 하지만 회상(recall)을 우선시하는 엔드 투 엔드 검색 엔드포인트에만 접근할 수 있는 경우, 해당 엔드포인트를 사용하면 모델 컨텍스트에 대량의 관련 없는 정보가 도입됩니다. 반면, 각각 다른 검색 전략이 필요한 여러 정보가 필요한 경우, 동일한 차선의 파이프라인을 모두에 대해 순차적으로 호출해야 할 수 있으며, 결과적으로 비용이 증가하고 컨텍스트가 노이즈로 가득 차게 됩니다.

도메인 지식 활용 실패. 많은 경우 모델은 검색 전략을 안내해야 하는 도메인 지식(학습, 에이전트 스킬, 메모리 또는 LLM 궤적의 이전 토큰에서 얻은 지식)을 가지고 있을 수 있습니다. 그러나 경직된 검색 인터페이스는 모델이 해당 지식을 활용하는 것을 방해합니다. 예를 들어, 모델은 특정 요청에 대해 어휘 및 의미론적 신호를 특정 방식으로 혼합하거나, 특정 소스의 우선순위를 지정하거나, 특정 키별로 결과를 집계해야 함을 깨달을 수 있습니다. 그러한 통찰력이 질의 매개변수를 통해 구현될 수 있는 경우가 아니라면, 모델은 실제로 그것에 대해 행동할 수 없습니다.

비효율적인 제어 흐름 및 컨텍스트 오염. 많은 검색 워크플로우는 자연스럽게 순차적이지 않습니다. 질의 변형에 대한 팬아웃, 병렬 페칭, 중복 제거 및 비선형적이고 비동기적인 제어 흐름이 필요한 기타 작업이 필요할 수 있습니다. 반복적인 모델 턴을 통해 이러한 단계를 강제하면 대기 시간이 늘어나고 워크플로우를 최적화하기가 더 어려워집니다. 또한 모델의 추론에 유용하지 않을 수 있는 노이즈가 많은 중간 상태로 모델 컨텍스트를 오염시켜 성능 저하와 잦은 압축을 초래합니다.

AI의 함수 호출 및 MCP 시대에는 이러한 문제에 대해 할 수 있는 일이 많지 않았습니다. 각 검색 작업이 LLM 추론으로의 자체 왕복을 필요로 할 때, 개발자는 당연히 그 왕복에서 가능한 한 많은 작업을 완료하기를 선호합니다. 이는 모델이 직접 소비할 수 있도록 완전히 처리된 결과 집합을 반환하는 엔드 투 엔드 검색 파이프라인을 의미합니다.

결과적으로 오늘날 대부분의 AI 대상 검색 시스템은 여전히 이러한 모놀리식 계약 하에서 작동합니다. 그러나 모델 지능과 사용자 요구가 지속적으로 성장함에 따라 그 계약의 단점은 더욱 두드러집니다. 코드 우선 하네스를 기반으로 구축된 오늘날의 가장 진보된 AI 시스템은 매분 수천 개의 작업을 실행하는 작업별 워크플로우를 구성할 수 있습니다. 검색 시스템은 아직 이러한 잠재력을 완전히 실현하지 못했습니다.

우리는 오랫동안 AI 네이티브 검색을 위한 적절한 경계가 스택의 더 낮은 곳에 있다고 의심해 왔습니다. 모델은 단순히 검색 엔진을 호출해서는 안 됩니다. 특정 작업의 요구에 따라 검색 스택의 개별 구성 요소를 조율할 수 있어야 합니다. 그것은 근본적으로 다른 아키텍처를 필요로 합니다.

프로그래밍 가능한 검색 아키텍처 설계

차세대 검색 아키텍처는 하나의 핵심 원칙, 즉 검색은 AI 에이전트에 의해 네이티브하게 프로그래밍 가능해야 한다는 원칙에 달려 있습니다. 에이전트는 미리 정해진 검색 파이프라인 세트에 제한되어서는 안 됩니다. 오히려 에이전트는 다양한 추상화 수준에서 설계된 구성 가능한 구성 요소를 사용하여 특정 작업에 필요한 파이프라인을 구축할 수 있어야 합니다.

우리의 새로운 Search as Code (SaC) 아키텍처는 이 원칙을 구현합니다. SaC에서는 함수 호출이나 MCP 인터페이스를 통해 단 하나의 검색 작업도 전달되지 않습니다. 대신 모든 작업은 모델이 생성한 Python 코드를 통해 조율됩니다. 가장 간단한 검색 요구 사항의 경우 이 코드는 고급 검색 엔드포인트에 대한 몇 가지 요청으로 구성될 수 있습니다. 그러나 복잡한 작업의 경우 코드는 조건부 실행, 비동기성, 병렬 처리 및 광범위한 저수준 기본 요소 호출을 포함하여 필요한 만큼 복잡할 수 있습니다.

Search as Code (SaC) 아키텍처는 Perplexity의 검색 인프라 위에 있는 모델, 컴퓨팅 샌드박스 및 에이전트 검색 SDK로 구성된 스택에 의존합니다.

SaC는 긴밀하게 결합된 세 가지 계층을 포함합니다:

모델은 제어 평면 역할을 합니다. 모델은 사용자(또는 상위 에이전트)의 지시를 추론하고, 지시를 작업으로 분해하며, 각 작업에 어떤 검색 및 처리 파이프라인이 필요한지 결정하고, 해당 파이프라인을 구현하기 위한 코드를 생성합니다.

컴퓨팅 샌드박스는 보안 코드 실행 런타임을 통해 결정론적 컴퓨팅을 제공합니다. 샌드박스는 모델이 제어 흐름, 배치, 재시도, 필터링, 결합, 집계 및 기타 결정론적 작업을 구현할 수 있는 캔버스를 제공합니다.

우리의 에이전트 검색 SDK는 Perplexity의 검색 스택을 구성 가능한 기본 요소로 노출합니다. 이 SDK는 저수준 검색 작업부터 고수준 의미론적 파싱까지의 빌딩 블록을 제공합니다. SDK는 샌드박스의 실행 런타임 내에 내장되어 모델이 단일 추론 턴 내에서 최대 수천 개의 작업을 조율할 수 있도록 합니다. 아래에서 각 계층에 대한 설계 결정 사항을 논의합니다.

에이전트 검색 SDK

에이전트 검색 SDK는 프로그래밍 가능한 검색을 위한 빌딩 블록을 정의합니다. 중요한 점은 우리 SDK가 라이브러리로 패키징된 기존 검색 API가 아니라는 것입니다. 지난 몇 달 동안 우리의 엔지니어링 팀은 검색 스택을 모듈식의 구성 가능한 기본 요소로 재설계했습니다. 우리는 에이전트 검색 SDK가 이러한 기본 요소에 직접 접근할 수 있도록 구축하여, 모델이 작업별 검색 파이프라인을 조율할 수 있는 훨씬 더 강력한 캔버스를 제공합니다.

고수준의 엔드 투 엔드 검색 파이프라인은 여전히 SDK 내에서 사용할 수 있지만, 더 이상 유일한 옵션은 아닙니다. 오히려 일반적인 검색 패턴에 대한 약어 형식으로 사용됩니다. 모델은 작업 요구 사항에 따라 자유롭게 사용하거나 우회할 수 있습니다.

런타임 선택: 우리는 Python, Rust, TypeScript 및 Bash를 SDK 런타임으로 고려했습니다. Python은 그 보편성과 데이터 처리 라이브러리 생태계를 고려할 때 가장 자연스러운 선택이 될 것이라고 생각했습니다. 내부 테스트를 통해 이것이 사실임이 확인되었으며, 오늘 출시되는 SDK 버전은 Python 기반입니다. 우리는 런타임이 최고의 에이전트 경험을 지속적으로 제공할 수 있도록 정기적으로 런타임 선택을 재평가할 예정입니다.

자동 연구를 통한 지속적인 개선: 우리는 또한 반복적인 자동 연구 루프를 통해 최신 LLM을 위한 SDK의 소비 가능성을 최적화했습니다. 몇 주 동안 지속적으로 실행되는 이 루프는 대기 시간, 코드 생성 품질 및 전반적인 작업 성능을 포함한 지표에 대해 SDK 개선 사항을 제안하고 검증합니다. 자동 연구 루프는 이미 SDK의 구조와 미학에 수많은 변화를 주었으며 모든 차원에서 상당한 이득을 얻었습니다. 우리는 새로운 최신 모델과 검색 구성 요소가 등장함에 따라 자동 연구를 통해 SDK를 더욱 개선할 계획입니다.

샌드박스

샌드박스는 SaC 파이프라인을 정의하고 실행하기 위한 보안 환경을 제공합니다. 샌드박스는 모델이 생성한 코드를 실행하며, 개별 검색 기본 요소와의 상호 작용을 촉진하기 위해 에이전트 검색 SDK에 대한 접근 권한을 제공합니다.

우리는 샌드박스를 최적화하고 강화하는 데 상당한 투자를 했으며, 그 전반적인 시스템 설계는 별도의 기사로 다룰 가치가 있습니다. 여기서는 SaC와 가장 관련이 깊은 설계 고려 사항인 중간 상태 관리에 중점을 둡니다.

SaC는 에이전트가 단일 추론 턴 내에서 복잡한 파이프라인을 조율할 수 있도록 지원합니다. 그러나 특정 중간 상태는 턴 간에 전달되어야 합니다. 예를 들어, 모델은 턴 1에서 일부 문서를 가져오고, 턴 2에서 해당 문서의 하위 샘플을 검사하여 다음에 무엇을 할지 결정한 다음, 턴 3부터 해당 문서를 추가로 조사하기 위한 다운스트림 검색 파이프라인을 개발할 수 있습니다. 위에서 논의한 바와 같이 토큰 공간을 통해 중간 상태를 전달하는 것은 효과적인 전략이 아닙니다.

우리는 턴 간에 중간 상태를 관리하기 위해 두 가지 접근 방식을 고려했습니다:

영구 파일시스템 + 명시적 직렬화/역직렬화(serde): 샌드박스는 모델이 턴 간에 사용할 수 있는 영구 파일시스템을 노출할 수 있습니다. 중간 상태를 유지하려는 모델은 턴에 대한 생성된 코드 내에 직렬화 단계를 포함하고, 후속 턴 내에 역직렬화 단계를 포함할 수 있습니다(모델 자체의 검사 또는 다운스트림 사용을 위해). 파일시스템 접근 방식은 모델이 중간 상태가 턴 간에 전달되는 방식을 직접적이고 명시적으로 제어할 수 있게 합니다. 또한 모델이 사용하는 정보의 명시적인 식별과 지속성을 강제하여 추적 가능성을 보장합니다. 한 가지 단점은 serde 코드를 생성하는 데서 발생하는 대기 시간 및 컨텍스트 오버헤드입니다. 잘 설계된 유틸리티 함수가 이 오버헤드를 완화할 수 있습니다.

REPL: 대안으로 샌드박스는 REPL 스타일 환경에서 턴 간에 실행 런타임 자체를 유지할 수 있습니다. 이를 통해 모델은 이전 턴에서 정의하거나 수정한 변수를 후속 턴에서 단순히 이름으로 참조할 수 있으므로 전혀 직렬화할 필요 없이 메모리 내에서 중간 상태를 유지할 수 있습니다. REPL 접근 방식은 serde 코드를 생성할 필요가 없으므로 더 토큰 효율적입니다. 그러나 명시적인 직렬화 단계가 없으면 100셀 Jupyter 노트북 작업 경험이 있는 사람에게 익숙한 이유로 다운스트림 성능이 저하될 수 있습니다. 변수 네임스페이스가 복잡해짐에 따라 턴 간에 정확히 무엇이 유지되는지, 그리고 그 이유를 추적하기가 더 어려워지기 때문입니다.

우리는 두 가지 접근 방식을 모두 테스트했으며 일반적인 사용에서는 비슷하게 수행되지만, 파일시스템 기반 serde가 특히 긴 궤적에서 더 나은 신뢰성을 제공한다는 것을 발견했습니다. 따라서 우리는 파일시스템 기반 serde를 솔루션으로 채택합니다. 우리는 모델이 상태를 암시적으로가 아니라 선언적으로 전달하도록 요구하는 것이 모델이 해당 상태를 더 효과적으로 관리하는 데 도움이 된다고 추측합니다. 이는 잠정적인 발견이며 우리는 두 접근 방식을 모두 계속해서 반복할 것입니다.

모델

에이전트 하네스를 구동하는 모델은 SaC의 제어 평면 역할을 합니다. 각 작업의 요구 사항을 충족하기 위해 에이전트 검색 SDK의 빌딩 블록에서 검색 파이프라인을 동적으로 조립한 다음, 샌드박스 실행을 위해 코드로 해당 파이프라인을 전달합니다.

Perplexity는 에이전트 하네스 내에서 다양한 모델을 사용하며, 최신 최신 모델이 범용 코드 생성 전반에 걸쳐 매우 효과적임을 발견했습니다. 주요 과제는 에이전트 검색 SDK를 위해 특별히 효과적인 코드 생성을 유도하는 것입니다. 즉, 어떻게 하면 모델이 SDK의 빌딩 블록을 작업 최적화 파이프라인으로 효과적으로 엮을 수 있을까요?

언어의 표준 라이브러리와 달리 맞춤형 SDK는 사전 학습 데이터에 포함될 가능성이 낮습니다. 자동 연구를 통한 SDK 소비 가능성 개선에도 불구하고 많은 모델은 여전히 함수 호출 및 직접적인 MCP 호출을 통해 검색 시스템과 상호 작용하도록 훈련되어 있습니다. 이러한 모델은 소스 코드와 자동 생성된 문서만으로 SDK를 능숙하게 휘두를 가능성이 낮습니다.

이 과제를 해결하기 위해 우리는 모델이 우리의 SDK를 효과적으로 활용하도록 가르치기 위해 고도로 튜닝된 에이전트 스킬을 개발했습니다. 초기 버전은 Perplexity의 스킬 설계 원칙에 따라 개발되었으며, SDK 최적화에 사용된 것과 동일한 지표에 중점을 둔 전용 자동 연구 루프를 통해 최적화되었습니다. 또한 컨텍스트 부풀림을 방지하기 위해 스킬 크기를 제한하며, 최종 버전은 루트 SKILL.md 파일의 토큰 수가 2,000개 미만입니다.

최적화된 스킬은 SDK의 사용 가능한 빌딩 블록을 나열하는 수준을 넘어섭니다(런타임 리플렉션을 통해 쉽게 얻을 수 있는 정보). 토큰의 대부분은 이러한 블록을 복잡한 패턴으로 구성하기 위한 간결하고 일반화 가능한 지침과 퓨샷 예제를 제공하는 데 사용됩니다. 이러한 스킬을 갖춘 모델은 SDK를 효과적으로 활용하여 수천 개의 개별 작업으로 확장되는 검색 파이프라인을 조율하는 것을 관찰할 수 있습니다.

오케스트레이터 및 갭 필러로서의 코드

이러한 계층을 결합함으로써 SaC는 모델과 검색 스택 간의 관계를 변경합니다. 고정 파이프라인 검색 시스템에서 모델은 검색 위에 위치하며 좁은 순차적 호출자 인터페이스를 통해 상호 작용합니다. SaC에서 모델은 검색 프로세스 자체를 조율하는 적극적인 참여자가 됩니다. 검색 스택의 모든 요소는 모델이 직접 프로그래밍할 수 있게 되며, 샌드박스와 에이전트 검색 SDK는 해당 요소에 필요한 인터페이스를 제공합니다.

하지만 네이티브로 존재하지 않는 기능은 어떨까요? 코드는 기존 기능을 조율하기 위한 강력한 매체입니다. 그러나 코드의 힘은 조율을 넘어섭니다. 코드는 또한 검색 스택이나 SDK에 존재하지 않는 기능에 대한 간극 채우기(gap-filler) 역할을 할 수 있습니다. 에이전트는 간결함으로부터 혜택을 얻으며, SDK가 전용 함수로 모든 잠재적 작업을 다루는 것은 비효율적입니다. 대신 SDK는 가장 근본적인 기본 요소를 제공하며, 모델은 코드로 추가 구성 요소를 즉석에서 구축할 수 있습니다.

예를 들어 검색 시스템 자체의 질의 구문으로는 효율적으로 구현할 수 없는 복잡한 정규식을 고려해 보십시오. 코딩 기능이 없다면 모델은 최선의 근사치를 생성하고, 질의를 수행하며, 매우 노이즈가 많은 결과 집합에 대해 토큰 공간 필터링을 수행해야 합니다. SaC를 사용하면 모델은 대신 원하는 정규식 결과 집합의 상위 집합을 수집하기 위해 병렬 SDK 호출을 수행하는 프로그램을 생성할 수 있습니다. SDK를 통해 중복 제거를 수행한 후 모델은 추가 코드를 작성하여 결과를 정확한 정규식으로 결정론적으로 좁힐 수 있습니다. 이런 방식으로 에이전트는 너무 니치한 서브루틴으로 SDK를 부풀리지 않고도 맞춤형 검색 기능을 구현할 수 있습니다.

사례 연구: CVE 벤더 권고

우리는 테스트 제품군 내의 실제 작업을 기반으로 한 사례 연구를 제시합니다. 이 작업은 에이전트에게 2023–2025년의 200개 이상의 고위험 CVE를 식별하고 특성화할 것을 요청합니다. 각 기록은 영향받는 벤더의 자체 권고를 인용하고, 제품 및 수정 버전을 명명하며, 수정 버전이 특정 CVE와 연결되어 있음을 보여야 합니다.

SaC의 답변은 정확도 100%를 기록했으며, 비 SaC 베이스라인 대비 총 토큰 사용량이 85.1% 감소했습니다(288.7K 토큰에서 42.9K 토큰으로). 섹션 4에서 더 자세히 논의되는 테스트된 비 Perplexity 시스템은 모두 25% 미만의 점수를 받았습니다.

우리는 SaC의 프로그래밍 가능성이 어떻게 모델이 효과적인 전략을 구현할 수 있게 하는지 설명하기 위해 궤적에서 세 가지 양식화된 코드 블록을 제시합니다.

python
# 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"]) ]

이 첫 번째 블록은 순수한 조율입니다. 생성된 프로그램은 소스 클래스 규칙을 질의 계획에 직접 인코딩하는 것으로 시작합니다. 즉, 벤더 소유의 권고 형식만이 관련이 있습니다. NVD, MITRE, CVE Details, 뉴스 스토리, CERT 페이지 및 타사 데이터베이스를 포함한 비 벤더 소스는 구조적으로 범위 밖입니다. 정확한 구문 제약 조건 또한 검색을 다운스트림에 필요한 정확한 CVE 세부 정보를 이미 포함하고 있는 인덱싱된 텍스트 페이지로 유도합니다.

python
# 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, )

두 번째 블록은 LLM을 중간 계획 서브루틴으로 사용합니다. 코드는 어떤 벤더-연도 쌍이 충분한 후보 페이지를 생성하고 있는지 요약하고, 목표 수정 사항을 요청하며, 실행 전에 각 제안된 질의를 검증합니다. 이는 사이트 범위의 정확한 구문 프로브 및 적응형 백필링과 같은 궤적의 유용한 패턴을 유지하면서 SDK에 맞춤형 CVE 권고 크롤러를 하드코딩하지 않습니다.

python
# 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")

마지막 블록은 결과 검증기로, 그 로직은 코드 생성을 통해 에이전트에 의해 완전히 정의됩니다. 검색 서브루틴은 그럴듯한 권고 페이지를 찾을 수 있지만, 이 작업은 더 엄격한 관계를 요구합니다. 즉, 권고는 하나의 CVE를 하나의 영향을 받는 제품 및 하나의 수정 버전과 벤더가 작성한 텍스트로 묶어야 합니다. 스키마는 해당 관계를 명시적으로 만들어 다운스트림 코드가 CVE별로 중복을 제거하고, 애그리게이터 URL을 거부하며, 약한 버전 증거를 폐기하고, 기록 수 최소값에 도달할 때까지 백필링을 계속할 수 있도록 합니다.

평가 결과

우리는 포괄적인 벤치마크 제품군에서 SaC의 효과를 평가하며, 절대 성능과 비용-성능 한계 모두에 중점을 둡니다.

벤치마크 및 시스템

우리의 벤치마크 제품군은 다양한 도메인, 작업 형식 및 복잡성 수준에서 검색 의존적 AI 워크플로우를 스트레스 테스트하도록 설계된 총 5개의 벤치마크로 구성됩니다. 우리는 네 가지 기존 벤치마크인 DeepSearchQA (DSQA), BrowseComp, Humanity's Last Exam (HLE), WideSearch를 사용합니다. 처음 세 가지 벤치마크(DSQA, BrowseComp 및 HLE)의 경우 정확도를 최상위 지표로 보고합니다. WideSearch의 경우 행별 F1 점수를 보고합니다.

우리는 또한 검색, 컴퓨팅 및 모델 추론의 신중한 조율이 필요한 어려운 “광범위한 연구” 작업에 중점을 둔 새로 개발된 WANDR 벤치마크를 사용합니다. WANDR은 Perplexity Computer가 사용자를 위해 처리하는 지식 집약적인 전문 작업에서 영감을 받았습니다. 이는 WideSearch 및 유사한 벤치마크를 반복하지만 더 복잡한 작업 및 작업 구조를 강조합니다. 우리는 앞으로 몇 주 내에 WANDR 벤치마크를 게시할 것입니다.

우리는 5개의 에이전트 기반 시스템을 평가합니다. 병렬화의 이점이 아닌 기본 아키텍처의 성능을 격리하기 위해 “Best-of-N” 점수가 아닌 개별 실행을 고려합니다. 각 시스템의 구성은 다음과 같습니다:

Perplexity (SaC): Perplexity의 프로덕션 Agent API 내에서 SaC 아키텍처를 평가합니다. GPT 5.5(고수준 추론)가 기본 모델 역할을 합니다.

OpenAI: 검색 (web_search) 및 Python 런타임 (code_interpreter)이 모두 활성화된 OpenAI Responses API를 평가합니다. GPT 5.5(고수준 추론)가 기본 모델 역할을 합니다.

Anthropic: 20260401 에이전트 툴셋 및 자동 허용 명령이 포함된 Anthropic Managed Agents를 평가합니다. Opus 4.7(고수준 추론)이 기본 모델 역할을 합니다.

Exa: 노력 수준을 높게 설정하여 프로덕션 API를 통해 Exa Agent를 평가합니다.

Parallel: 프로세서를 ultra4x로 설정하여 프로덕션 API를 통해 Parallel Tasks를 평가합니다.

비교 성능

표 1은 각 시스템에 대한 벤치마크 점수를 보고합니다. SaC는 5개 벤치마크 중 4개에서 다른 모든 시스템을 능가합니다. 나머지 벤치마크(HLE)에서 SaC는 기본적으로 OpenAI Responses와 공동 1위를 기록했습니다. 소개의 그림 2는 이러한 점수를 그래픽 형식으로 시각화합니다.

벤치마크

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

표 1 | 각 평가된 시스템에 대한 벤치마크 점수. 행별 최고 점수는 굵게 표시.

SaC는 벤치마크 제품군 전반에서 최첨단 성능을 달성하지만, 그 이점은 WANDR에서 특히 두드러집니다. 그림 5는 WANDR 점수를 분석하여 Perplexity의 SaC 구현이 차선책 시스템보다 2.5배 더 뛰어난 성능을 보임을 보여줍니다. 이러한 큰 격차에도 불구하고 WANDR은 여전히 포화 상태가 아니며 SaC에게도 도전적인 과제임을 입증합니다. 우리는 WANDR 작업이 요구하는 복잡하고 매우 수평적인 검색 워크플로우가 일관되게 높은 성능을 달성하기 위해 연구 및 검색 엔지니어링의 추가적인 발전을 필요로 할 것이라고 믿습니다.

평가된 시스템 전반의 WANDR 점수. Perplexity Agent API가 차선책 시스템보다 2.5배 앞서 있습니다.

마지막으로, 우리는 동일한 Perplexity 검색 인프라를 활용하는 보다 전통적인 검색 파이프라인과 비교하여 SaC의 상대적 이득을 측정합니다. 그림 6은 각 벤치마크에서 SaC와 비 SaC 아키텍처 간의 점수 차이를 보고합니다. 전반적으로 SaC는 상당한 성능 향상을 제공하며, DSQA에서 가장 큰 절대 이득(+19.77pp, 29%), WANDR에서 가장 큰 상대적 이득(+12.00pp, 45%)을 보입니다.

각 벤치마크에서의 Perplexity 베이스라인 대 SaC 점수(절대 및 상대 델타 주석 포함).

비용-성능 한계

실제로 사용자는 비용 대비 성능에 관심이 있습니다. 따라서 우리는 DSQA 및 WideSearch에서 비용-성능 한계를 평가합니다. 우리는 다른 시스템과 함께 낮음, 중간 및 높음 모델 추론 수준 전반에 걸쳐 SaC의 비용과 성능을 측정합니다. 그림 7과 8은 작업당 가격 대비 벤치마크 점수를 플롯으로 나타내며, x축이 반전되어 있어 오른쪽으로 갈수록 더 저렴하고 위쪽으로 갈수록 더 나은 성능을 나타냅니다.

DSQA 점수 대 작업당 가격. 점선은 SaC 모델 추론 구성을 연결합니다.

DSQA에서 세 가지 SaC 설정 모두 오른쪽 상단 경계에 있습니다. 낮은 추론 설정은 다른 모든 시스템보다 저렴하면서도 그 중 두 시스템보다 더 나은 성능을 보입니다. 중간 추론 설정은 작업당 $1 미만에서 모든 비 SaC 시스템을 능가합니다. 높은 추론 설정은 경쟁력 있는 비용으로 최고의 성능을 달성합니다.

WideSearch 점수 대 작업당 가격. 점선은 SaC 모델 추론 구성을 연결합니다.

WideSearch는 유사한 모양의 경계를 보여줍니다. DSQA와 마찬가지로 낮은 추론 설정은 모든 비 SaC 시스템보다 저렴한 비용으로 경쟁력 있는 성능을 달성하며, 중간 및 높은 추론 설정 모두 작업 성능 면에서 비 SaC 시스템을 능가합니다.

새로운 컴퓨팅 아키텍처를 향하여

Search as Code는 소프트웨어 설계의 광범위한 변화를 반영합니다. 수십 년 동안 소프트웨어 시스템은 CPU의 전통적인 런타임에 의해 실행되는 결정론적 명령을 중심으로 조직되었습니다. 최신 모델은 지시를 따르고 생성할 수 있는 새로운 형태의 컴퓨팅, 즉 토큰 공간 추론을 도입합니다. 가장 유능한 컴퓨팅 시스템은 둘 중 하나를 선택하는 대신 이 두 가지 형태의 컴퓨팅을 결합할 것입니다.

검색은 이 하이브리드 아키텍처를 위한 자연스러운 테스트 베드입니다. 모델은 어떤 증거가 필요하고 불확실성이 어떻게 해결되어야 하는지 결정하는 데 적합합니다. 결정론적 런타임은 배치, 병렬 처리, 필터링, 순위 지정 및 집계에 적합합니다. 검색 인프라는 범용 I/O 계층 역할을 하며, 분당 수천 개의 작업을 유지할 수 있는 세계의 정보에 대한 유용한 핸들을 런타임에 제공합니다. 이러한 조각들이 통합되면 결과 시스템은 실제 작업을 수행하는 데 훨씬 더 강력하고 효율적이 됩니다.

이 아키텍처의 모든 부분은 이러한 기능을 잠금 해제하는 데 필요합니다. 지능형 모델 없이는 시스템이 검색 전략에 대해 추론할 수 없습니다. 샌드박스 없이는 모델이 순차적 I/O 및 비효율적인 토큰 공간 처리를 강요받습니다. 그리고 원자화된 검색 스택 없이는 모델이 조율할 대상이 없습니다. SaC가 작동하는 이유는 추론, 결정론적 컴퓨팅 및 I/O가 각 계층의 강점을 강조하기 위해 공동 설계되었기 때문입니다.

이러한 공동 설계는 지속적인 개선 루프의 개발을 통해 더욱 발전될 수 있습니다. 예를 들어 에이전트 검색 SDK와 SaC 에이전트 스킬은 공통 자동 연구 루프에서 공동으로 최적화될 수 있습니다. 더 야심 차게는 모델이 SDK로 노출된 저수준 검색 기본 요소를 활용하도록 훈련될 수 있습니다. 모델 훈련 과정 자체에서 SDK 설계를 공동 진화시키려 시도할 수도 있습니다. 우리는 향후 작업에서 더 공격적인 공동 설계 전략을 추구하기를 기대합니다.

우리는 모델이 단순히 결과를 소비하는 것이 아니라 검색 프로세스를 제어할 수 있도록 SaC를 구축했습니다. 우리의 결과는 이 제어의 힘을 입증합니다. SaC는 지식 집약적인 에이전트 벤치마크에서 절대 성능과 비용-성능 한계를 모두 발전시킵니다. 우리는 오늘부터 Perplexity Computer와 Agent API를 시작으로 SaC의 기능을 사용자에게 제공하게 되어 기쁩니다. 우리는 사용자와 그들을 서비스하는 에이전트가 가장 강력하고 효율적인 검색 기능을 가질 수 있도록 스택의 모든 계층에서 SaC 아키텍처를 계속 최적화할 것입니다.

인용

BibTeX
@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}
}