Search as Code生成の再考
モノリシックなサービスから、エージェントハーネス時代のプログラム可能なプリミティブへと検索を進化させる。
検索はAIシステムにとって中心的なプリミティブです。フロンティアモデルは月を追うごとに能力が向上していますが、それでも依然として、より広い世界からの新鮮で正確、かつ適切にキュレーションされた知識へのアクセスを必要としています。検索はAIシステムがそうした知識を活用するための主要な手段であり、結論を導き出し、行動を起こし、現実世界のタスクを遂行する必要があるあらゆる製品にとって、基盤となるコンポーネントです。
私たちは、エージェントの時代において、従来の検索パイプラインがますます時代遅れになりつつあると考えています。従来の検索はクエリに対して回答を提供しますが、現代のエージェントは、無数の形態をとるタスクを完遂します。これらのタスクでは、エージェントがタスク固有の検索戦略を自身のハーネス内で直接定義することが求められます。Perplexity Computerでは、単一のタスクが数分以内に数百、あるいは数千もの検索操作を呼び出す様子を目にしました。これは人間には不可能ですが、エージェントにとっては極めて自然なワークフローです。
この世界では、検索そのものがエージェント的である必要があり、その構成要素はエージェントハーネス内のSDKとして直接アクセス可能でなければなりません。私たちは、Perplexityの新しい参照検索アーキテクチャとして「Search as Code (SaC)」を導入します。
はじめに
Perplexityの検索スタックは、当社のアプリケーションおよびAPIプラットフォーム全体で毎秒数千ものクエリを処理しています。2025年9月、私たちは検索システムの最初のアーキテクチャ概要を公開しました。これらのシステム内における継続的なイノベーションは、Search API、Agent API、Computerといった新しいサービスの立ち上げを支えており、自己改善ループが日々検索スタックを最適化し、ユーザーにより良いサービスを提供しています。
従来、AIシステムは検索をモノリスとして扱ってきました。つまり、AIモデルがクエリを発行し、検索エンジンが定義済みのパイプラインを実行し、モデルがその結果をコンテキストとして消費するというものです。大半において、これは初期のAIユーザーのニーズに対応するには十分でした。リクエストが比較的単純であったため、検索パイプラインが正確にどのように設計されているか、あるいはパイプラインのアーキテクチャがそのタスクに対して最適であるかどうかを懸念する理由はありませんでした。デフォルトのインターフェース(関数呼び出しやMCPなど)と同様に、デフォルト設定で十分であると見なされていました。
しかし今日、このアプローチは月を追うごとに時代遅れになっています。ユーザーはAIに対して単発的な分析以上のものを求めています。彼らは、エージェントが数時間、あるいは数日にわたってエンドツーエンドでタスクを完遂することを期待しています。こうしたタスクは複雑で、オープンエンドであり、情報ニーズが高度に変動する可能性があるため、モノリシックなアーキテクチャはこれらの要求の重圧の下で崩壊しつつあります。
AI の最も重要なボトルネックは、最終的には 制御 の問題です。フロンティアモデルは、固定されたコンテキストに対する推論ではすでにかなり優れています。しかし、最も強力な AI システムには、そのコンテキストをモデルに対してどのように取得し、処理し、集約し、レンダリングするかを 制御する 能力が必要になります。
従来の検索システムは、このレベルの制御可能性を考慮して設計されていませんでした。結局のところ、たとえ提供されたとしても、人間のユーザーが検索パイプラインの内部構造に対してきめ細かい制御を行うことは期待できません。初期のAIモデルは、関数呼び出しとMCPの線形的な軌跡を通じてのみ検索を制御できました。しかし、コード実行能力を持つエージェントハーネスによって駆動される今日のフロンティアモデルは、コンピュータコードを通じて想像しうるあらゆる計算プリミティブに対して、きめ細かい制御を行使することができます。私たちの課題は、適切なプリミティブを提供することにあります。
このニーズを満たすため、私たちは製品全体に新しい検索アーキテクチャを導入します。それが「Search as Code (SaC)」です。この新しいアーキテクチャは、モデルが最終的な出力のみを消費するのではなく、検索スタックそのものに「踏み込む」ことを可能にします。核心となる考え方は単純です。検索スタックのコンポーネントをSDK内のプリミティブとして公開します。検索を必要とするあらゆるリクエストに対して、モデルはこれらのプリミティブをオンデマンドで組み立て、そのリクエストに合わせた検索パイプラインを構築します。
このパイプラインの構築は、安全なサンドボックス内でのコード生成と実行を通じて行われます。検索に対する他のコード生成主導型アプローチとは異なり、私たちは単に従来の検索APIをシェルや言語ランタイム内に配置するだけではありません。私たちは、検索の個々の構成要素を可能な限り最も原子的なレベルで公開するエージェント的検索SDKを慎重に設計しました。
これらの構成要素を備えたSaCは、検索、ランキング、フィルタリング、ファンアウト、レンダリングなど、各検索ステップに対する直接的な制御をモデルに与えます。また、候補リストやランキングシグナルといった中間状態への効率的なアクセスもモデルに提供します。制御と可読性というこれら二つのレバーを組み合わせることで、エージェントは数千もの検索操作にまたがる特注の検索パイプラインを設計し、それらのパイプラインをリアルタイムで最適化し、最も有益な情報のみをモデルコンテキストとして消費することが可能になります。
本記事では、SaCの動機、設計、実装について、既存および新規のベンチマークにおける実証結果とともに説明します。SaCは、エージェント的検索のための新たな費用対効果のフロンティアを確立するものであり、これをユーザーやより広範なAIコミュニティと共有できることを嬉しく思います。
従来の検索の硬直性
世界初の検索エンジンは、人間のユーザーのために構築されました。これらのユーザーは、通常、関連性でランク付けされた一定数のドキュメントで構成される、予測可能なエクスペリエンスを期待するようになりました。ユーザーは検索プロセスを細かく管理することを望んでおらず、クエリを入力して有益な結果を見つけることを望んでいました。
その結果、人間向けの検索エンジンは、入力クエリに対して上位n件のヒットを含む、人間にとって使いやすい検索結果ページ(SERP)を生成することに特化した、共通のモノリシックなアーキテクチャに収束しました。このパターンは、消費者向け検索における数十年の進歩を牽引してきました。これは高速で親しみやすく、人間のブラウジングにとって非常に効果的です。
その後、LLMが登場し、AIシステムも検索の消費者となりました。Perplexityは、2022年に回答エンジンを立ち上げることでこの転換を先導しました。それ以来、私たちの検索エンジニアリングの取り組みは、AIモデルにとって検索結果の価値を最適化する方法に焦点を当ててきました。世界で最も正確で信頼性の高いAIを構築するために、私たちは各トークンを可能な限り情報密度が高いものにするための検索システムを構築する必要がありました。サブドキュメント検索、コンテキスト効率、意味理解、およびその他の重要な領域におけるその後のイノベーションは、AIシステムが情報を検索し、それに基づいて行動する能力の劇的な向上につながりました。
しかし、AI向けに最適化されたシステムでさえ、従来の検索エンジンと同じ基本的な契約を大部分において継承しています。それは、「クエリを受け入れ、定義済みの検索パイプラインを実行し、完全に処理された結果セットを返す」というものです。単純なリクエストの場合、このアプローチは問題なく機能します。しかし、より複雑なリクエストの場合、これはパフォーマンス、レイテンシ、コストを低下させる、ますます制限的なボトルネックとなります。
硬直性による失敗モード
従来の検索パイプラインは、クエリパラメータという単一の制御ポイントを中心に設計されています。検索エンジンが定義済みのロジックに従ってパイプラインの残りの部分を所有しており、モデルはそれに適応しなければなりません。モデルにとって、クエリパラメータの下流にあるものはすべて硬直的であり、実際の計算の形態はモデルの制御外にあります。
消費者がリンクをスキャンする人間である場合、これは理にかなった境界線です。しかし、消費者が閉ループで知識集約的なタスクを解決しようとするAIモデルである場合、これは不適切な境界線となります。私たちの経験では、この硬直性は3つの反復的な失敗モードを生み出しています。
粗いコンテキスト。 AIモデルは、コンテキストの品質とコンパクトさに敏感です。品質とコンパクトさはどちらもクエリに大きく依存しますが、モノリシックな検索パイプラインはすべてのクエリで最適に機能するように設計されていません。例えば、モデルが極めてピンポイントな情報を1つ必要としているにもかかわらず、リコールを優先するエンドツーエンドの検索エンドポイントしか利用できない場合、そのエンドポイントを使用すると、モデルのコンテキストに膨大な量の無関係な情報が混入してしまいます。その一方で、モデルがそれぞれ異なる検索戦略を必要とする多くの情報を必要としている場合、それらすべてに対して同じ最適とは言えないパイプラインを連続的に呼び出すことを強いられ、コストが膨れ上がり、コンテキストがノイズだらけになる可能性があります。
ドメイン知識を活用できない。 多くの場合、モデルは(トレーニング、エージェントスキル、メモリ、またはLLMの軌跡の以前のトークンから得られる)検索戦略を導くべきドメイン知識を持っている可能性があります。しかし、硬直的な検索インターフェースは、モデルがその知識を活用することを妨げます。例えば、モデルは特定のリクエストに対して、語彙シグナルと意味シグナルを特定の方法でブレンドしたり、特定のソースを優先したり、特定のキーで結果を集約したりすべきであると認識するかもしれません。これらの洞察がクエリパラメータを通じて実装可能でない限り、モデルは実際に行動に移すことができません。
非効率な制御フローとコンテキストの汚染。 多くの検索ワークフローは本質的に直列ではありません。クエリのバリエーション全体にわたるファンアウト、並列フェッチ、重複排除、および非線形かつ非同期の制御フローを必要とするその他の操作が必要になる場合があります。これらのステップをモデルの反復的なターンを通じて強制することは、レイテンシを増大させ、ワークフローを最適化しにくくします。また、モデルの推論に役立たない可能性のあるノイズの多い中間状態でモデルのコンテキストを汚染し、パフォーマンスの低下と、より頻繁な圧縮を招く結果となります。
AIの関数呼び出しとMCP時代には、これらの課題に対してできることはあまりありませんでした。各検索操作がLLM推論への独自のラウンドトリップを必要とする場合、開発者は自然とそのラウンドトリップで多くのことを成し遂げたいと考えます。これは、モデルが直接消費するために完全に処理された結果セットを返すエンドツーエンドの検索パイプラインを意味します。
その結果、今日のほとんどのAI向け検索システムは、依然としてこのモノリシックな契約の下で運用されています。しかし、モデルの知能とユーザーの要求が継続的に成長する中で、その契約の欠点がより顕著になっています。コードファーストのハーネスの上に構築された今日の最も高度なAIシステムは、毎分数千ものアクションを実行するタスク固有のワークフローを構成できます。検索システムは、この可能性を完全には実現できていません。
私たちは以前から、AIネイティブ検索にとって正しい境界線はスタックのより低い位置にあるのではないかと疑っていました。モデルは単に検索エンジンを呼び出すだけではいけません。特定のタスクの要求に応じて、検索スタックの個々のピースをオーケストレーションできる必要があります。それには、根本的に異なるアーキテクチャが必要です。
プログラム可能な検索アーキテクチャの設計
次世代の検索アーキテクチャは、1つの核心原則にかかっています。それは、「検索はAIエージェントによってネイティブにプログラム可能であるべきだ」ということです。エージェントは、あらかじめ決められた一連の検索パイプラインに限定されてはなりません。むしろ、さまざまな抽象化レベルで設計された構成可能なビルディングブロックを使用して、特定のタスクが必要とするパイプラインを構築できる必要があります。
私たちの新しいSearch as Code (SaC) アーキテクチャは、この原則を具体化したものです。SaCでは、関数呼び出しやMCPインターフェースを通じてディスパッチされる検索操作は一つもありません。すべての操作は、モデルが生成したPythonコードを介してオーケストレーションされます。最も単純な検索ニーズの場合、このコードは高レベルの検索エンドポイントへの少数のリクエストで構成されるかもしれません。しかし、複雑なタスクの場合、コードは条件付き実行、非同期、並列処理、および広範な低レベルプリミティブへの呼び出しを伴い、必要に応じて複雑なものにすることができます。
SaCは、密接に結合された3つのレイヤーで構成されています。
モデルはコントロールプレーンとして機能します。モデルはユーザー(または親エージェント)の指示を推論し、その指示をタスクに分解し、各タスクに必要な検索および処理パイプラインを決定し、それらのパイプラインを実装するためのコードを生成します。
計算サンドボックスは、安全なコード実行ランタイムを通じて決定論的な計算を提供します。サンドボックスは、制御フロー、バッチ処理、再試行、フィルタリング、結合、集約、およびその他の決定論的な操作をモデルが実装するためのキャンバスを提供します。
私たちのエージェント的検索SDKは、Perplexityの検索スタックを構成可能なプリミティブとして公開します。これは、低レベルの検索操作から高レベルの意味解析まで、ビルディングブロックを提供します。このSDKはサンドボックスの実行ランタイム内に埋め込まれており、モデルは単一の推論ターン内で最大数千もの操作をオーケストレーションできます。以下では、各レイヤーに対する設計上の決定について議論します。
エージェント的検索SDK
エージェント的検索SDKは、プログラム可能な検索のためのビルディングブロックを定義します。重要なのは、私たちのSDKはライブラリとしてパッケージ化された既存の検索APIではないという点です。過去数ヶ月間、当社のエンジニアリングチームは検索スタックをモジュール式で構成可能なプリミティブに再設計しました。私たちは、これらのプリミティブへの直接的なアクセスを提供するためにエージェント的検索SDKを構築し、モデルがタスク固有の検索パイプラインをオーケストレーションできる、はるかに強力なキャンバスを実現しました。
高レベルのエンドツーエンドの検索パイプラインは依然としてSDK内で利用可能ですが、それらが唯一の選択肢というわけではありません。むしろ、それらは一般的な検索パターンの省略形として機能します。モデルはタスクの要求に応じてそれらを自由に使用したり、回避したりすることができます。
ランタイムの選択: 私たちはSDKランタイムとしてPython、Rust、TypeScript、およびBashを検討しました。Pythonはそのユビキタス性とデータ処理ライブラリのエコシステムを考慮すると、最も自然な適合であると予想しました。社内テストでこれが事実であることが確認され、今日リリースされるSDKのバージョンはPythonベースとなっています。私たちは、最高のエージェント体験を提供し続けることを保証するために、定期的にランタイムの選択を見直す予定です。
オートリサーチを通じた継続的な改善: また、反復的なオートリサーチループを通じて、フロンティアLLMに対するSDKの消費可能性を最適化しました。数週間にわたって継続的に実行されるこのループは、レイテンシ、コード生成品質、全体的なタスクパフォーマンスなどの指標に基づいてSDKの改善案を提示し、検証します。オートリサーチループはすでにSDKの構造と美観の両面に数多くの変更を加えており、あらゆる面で大幅な向上を実現しています。新しいフロンティアモデルと検索コンポーネントが登場するにつれて、オートリサーチを通じてSDKをさらに洗練させる計画です。
サンドボックス
サンドボックスは、SaCパイプラインを定義および実行するための安全な環境を提供します。これらはモデルが生成したコードを実行し、個々の検索プリミティブとのやり取りを促進するためにエージェント的検索SDKへのアクセスを提供します。
私たちはサンドボックスの最適化と強化に多大な投資を行っており、その包括的なシステム設計自体が記事に値するものです。ここでは、SaCにとって最も重要な設計上の考慮事項である「中間状態の管理」に焦点を当てます。
SaCは、エージェントが単一の推論ターン内で複雑なパイプラインをオーケストレーションできるようにします。しかし、特定の中間状態はターンをまたいで伝達される必要があります。例えば、モデルがターン1でいくつかのドキュメントを取得し、次に何をすべきかを決定するためにターン2でそれらのドキュメントのサブサンプルを調査し、ターン3以降でそれらのドキュメントをさらに調査するための後続の検索パイプラインを開発したいと考えるかもしれません。前述の通り、トークンスペースを通じて中間状態を渡すことは、効果的な戦略ではありません。
私たちは、ターンをまたいで中間状態を管理するために、2つのアプローチを検討しました。
永続的なファイルシステム + 明示的なSerde: サンドボックスは、モデルがターンをまたいで使用できる永続的なファイルシステムを公開できます。中間状態を保持したいモデルは、生成されたコード内にターンごとのシリアライズステップを含め、その後のターン(モデル自身の検査用、または下流での使用用)でデシリアライズステップを含めることができます。ファイルシステムのアプローチにより、モデルはターンをまたいで中間状態がどのように伝達されるかを直接的かつ明示的に制御できます。また、モデルによって使用される情報の明示的な識別と永続化を強制することで、トレーサビリティも保証します。一つの欠点は、serdeコードの生成によって生じるレイテンシとコンテキストのオーバーヘッドですが、適切に設計されたユーティリティ関数によってこのオーバーヘッドを緩和できます。
REPL: あるいは、サンドボックスはREPLスタイルの環境で、ターンをまたいで実行ランタイム自体を永続化することもできます。これにより、モデルはシリアライズを一切行うことなく、中間状態をメモリ内に保持できます。前のターンで定義または変更された変数は、後のターンで名前で参照するだけでよいためです。REPLアプローチはserdeコードを生成する必要がないため、トークン効率が高くなります。しかし、明示的なシリアライズステップが欠如していると、100セルのJupyterノートブックを扱ったことがある人なら誰でも知っている理由で、下流のパフォーマンスを損なう可能性があります。変数名前空間が乱雑になると、何が正確にターンをまたいで永続化され、なぜそうなるのかを追跡することがより困難になります。
私たちは両方のアプローチをテストし、通常の使用では同様に機能するものの、ファイルシステムベースのserdeの方が特に長い軌跡において信頼性が高いことを発見しました。したがって、私たちはソリューションとしてファイルシステムベースのserdeを採用します。モデルに対し、状態を暗黙的ではなく宣言的に伝達することを要求することが、その状態をより効果的に管理する助けになると推測しています。これは暫定的な発見であり、今後も両方のアプローチを反復的に改善していく予定です。
モデル
エージェントハーネスを駆動するモデルは、SaCのコントロールプレーンとして機能します。各タスクのニーズに合わせてエージェント的検索SDKのビルディングブロックから検索パイプラインを動的に組み立て、それらのパイプラインをコードとしてサンドボックス実行のためにディスパッチします。
Perplexityは当社のエージェントハーネス内でさまざまなモデルを採用しており、最新のフロンティアモデルが汎用的なコード生成において全体的に非常に効果的であることを発見しました。主な課題は、エージェント的検索SDKのために特に効果的なコード生成を誘導することです。つまり、モデルにSDKのビルディングブロックを効果的に織り交ぜて、タスクに最適化されたパイプラインを構築させるにはどうすればよいか、ということです。
言語の標準ライブラリとは異なり、カスタム構築されたSDKが事前学習データ内に存在している可能性は低いです。オートリサーチによるSDKの消費可能性の向上をもってしても、多くのモデルは依然として関数呼び出しや直接的なMCP呼び出しを通じて検索システムとやり取りするようにトレーニングされています。これらのモデルがソースコードと自動生成されたドキュメントだけでSDKを巧みに使いこなす可能性は低いです。
この課題を解決するために、モデルに当社のSDKを効果的に活用させるための高度に調整されたエージェントスキルを開発しました。初期バージョンはPerplexityのスキルの設計原則に従って開発され、その後、SDK最適化で使用されるのと同じ指標に焦点を当てた専用のオートリサーチループを通じて最適化されました。また、コンテキストの肥大化を防ぐためにスキルサイズを制限しており、最終バージョンではルートのSKILL.mdファイルは2000トークン未満となっています。
最適化されたスキルは、単に利用可能なSDKのビルディングブロックをリストアップする(これはランタイムリフレクションを介して簡単に取得できることです)以上の機能を備えています。トークンの大部分は、これらのブロックを複雑なパターンに構成するための簡潔で汎用性のあるガイダンスとfew-shotの例を提供することに費やされています。これらのスキルを備えたモデルが、数千もの個別操作にスケールする検索パイプラインをオーケストレーションするためにSDKを効果的に活用する様子が確認されています。
オーケストレーターおよびギャップフィラーとしてのコード
これらのレイヤーを組み合わせることで、SaCはモデルと検索スタックの関係を変化させます。固定パイプライン検索システムでは、モデルは検索の上に位置し、狭い直列の呼び出しインターフェースを介してそれとやり取りします。SaCでは、モデルが検索プロセスそのものをオーケストレーションするアクティブな参加者となります。検索スタックのすべての要素がモデルによって直接プログラム可能になり、サンドボックスとエージェント的検索SDKがそれらの要素に対する必要なインターフェースを提供します。
しかし、ネイティブに存在しない機能についてはどうでしょうか。コードは既存の機能をオーケストレーションするための強力な媒体です。しかし、コードの力はオーケストレーションを超越します。検索スタックやSDKに存在しない機能のギャップフィラーとしても機能します。エージェントは簡潔さから恩恵を受けるため、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のプログラム可能性がモデルにいかに効果的な戦略の実装を可能にするかを示すため、軌跡から抽出した3つの定型的なコードブロックを紹介します。
# 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詳細がすでに含まれているページへと検索を誘導します。
# 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,
)2番目のブロックは、中間計画サブルーチンとしてLLMを使用します。このコードは、どのベンダー・年ペアが十分な候補ページを作成しているかを要約し、対象を絞った改善を要求し、実行前に各提案クエリを検証します。これにより、サイトスコープの完全一致フレーズプローブや適応的なバックフィリングなど、軌跡から有益なパターンが維持され、特注のCVE勧告クローラーを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")最後のブロックは、コード生成を通じてエージェントが論理を完全に定義する結果検証ツールです。検索サブルーチンはもっともらしい勧告ページを見つけることができますが、タスクにはより厳密な関係が必要です。つまり、勧告はベンダーが作成したテキストの中で、一つのCVEを一つの影響を受ける製品と一つの修正バージョンに結びつける必要があります。スキーマはその関係を明示的にするため、下流のコードはCVEごとに重複排除を行い、アグリゲーターURLを拒否し、弱いバージョンの証拠を破棄し、レコード数の下限に達するまでバックフィリングを続けることができます。
評価結果
私たちは、絶対的なパフォーマンスと費用対効果のフロンティアの両方に焦点を当て、包括的なベンチマークスイートでSaCの有効性を評価します。
ベンチマークとシステム
当社のベンチマークスイートは、さまざまなドメイン、タスク形式、複雑さレベルにわたって検索依存のAIワークフローをストレステストするために設計された、合計5つのベンチマークで構成されています。私たちは4つの既存ベンチマーク、DeepSearchQA (DSQA)、BrowseComp、Humanity's Last Exam (HLE)、WideSearchを使用します。最初の3つのベンチマーク(DSQA、BrowseComp、HLE)については、トップライン指標として精度を報告します。WideSearchについては、行ごとのF1スコアを報告します。
また、新しく開発されたWANDRベンチマークも使用します。これは、検索、計算、およびモデル推論の慎重なオーケストレーションを必要とする、困難な「ワイドリサーチ」タスクに焦点を当てています。WANDRは、Perplexity Computerがユーザーのために処理する知識集約的な専門的タスクに触発されています。これはWideSearchや類似のベンチマークを反復改善したものですが、より複雑なタスクとタスク構造を強調しています。今後数週間以内にWANDRベンチマークを公開する予定です。
5つのエージェントベースのシステムを評価します。並列化の利点ではなく、基礎となるアーキテクチャのパフォーマンスを分離するために、「ベストオブ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: 製品版APIを介してParallel Tasksを評価します。プロセッサは「ultra4x」に設定されています。
比較パフォーマンス
表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番目に優れたシステムを2.5倍の差で上回っていることを示しています。この大きな差にもかかわらず、WANDRは依然として未飽和であり、SaCにとっても挑戦的です。WANDRのタスクが必要とする複雑で高度に水平的な検索ワークフローが、一貫して高いパフォーマンスを達成するためには、研究と検索エンジニアリングにおけるさらなる進歩が必要であると考えています。
最後に、同じPerplexity検索インフラストラクチャを活用する、より伝統的な検索パイプラインに対するSaCの相対的な利得を測定します。図6は、各ベンチマークにおけるSaCアーキテクチャと非SaCアーキテクチャのスコアの差を報告しています。全体として、SaCは実質的なパフォーマンス向上を提供しており、DSQAでは最大の絶対利得(+19.77 pp、29%)、WANDRでは最大の相対利得(+12.00 pp、45%)を記録しています。
費用対効果のフロンティア
実際には、ユーザーはコストに対するパフォーマンスに関心があります。そのため、DSQAとWideSearchにおける費用対効果のフロンティアを評価します。他のシステムと並べて、低、中、高のモデル推論レベル全体でSaCのコストとパフォーマンスを測定します。図7および8は、タスクあたりの価格に対するベンチマークスコアをプロットしています。x軸を反転させているため、右側にあるほど安価であり、上にあるほど高いパフォーマンスを表します。
DSQAでは、3つのSaC設定すべてが右上フロンティア上にあります。低推論設定は、他のすべてのシステムよりも安価でありながら、そのうちの2つよりも優れたパフォーマンスを発揮します。中推論設定は、タスクあたり1ドル未満で、すべての非SaCシステムを上回ります。高推論設定は、競争力のあるコストでトップレベルのパフォーマンスを達成します。
WideSearchも同様の形状のフロンティアを示しています。DSQAと同様に、低推論設定はすべての非SaCシステムよりも低コストで競争力のあるパフォーマンスを達成し、中推論設定と高推論設定の両方がタスクパフォーマンスにおいて非SaCシステムを上回ります。
新しい計算アーキテクチャに向けて
Search as Codeは、ソフトウェア設計におけるより広範な変化を反映しています。何十年もの間、ソフトウェアシステムは、CPU上の従来のランタイムによって実行される決定論的な命令を中心に組織化されてきました。フロンティアモデルは、新しい形式の計算を導入します。それは、指示に従うことも生成することもできるトークンスペース推論です。最も有能な計算システムは、これら2つの計算形式の間で選択するのではなく、組み合わせることになります。
検索は、このハイブリッドアーキテクチャにとって自然な検証の場です。モデルは、どのような証拠が必要であり、どのように不確実性が解決されるべきかを決定するのに適しています。決定論的なランタイムは、バッチ処理、並列処理、フィルタリング、ランキング、集約に適しています。検索インフラストラクチャは普遍的なI/Oレイヤーとして機能し、毎分数千もの操作を維持できる、世界の情報に対する有用なハンドルをランタイムに提供します。これらのピースが統合されると、得られるシステムは現実世界のタスクを達成する上で、はるかに強力かつ効率的になります。
これらの能力を解放するためには、このアーキテクチャのあらゆる部分が必要です。インテリジェントなモデルなしでは、システムは検索戦略を推論できません。サンドボックスなしでは、モデルは直列I/Oと非効率的なトークンスペース処理を強いられます。そして、原子化された検索スタックなしでは、モデルはオーケストレーションするものが何もありません。SaCが機能するのは、推論、決定論的計算、I/Oが、各レイヤーの長所を強調するように共同で設計されているためです。
この共同設計は、継続的な改善ループの開発を通じてさらに推し進めることができます。例えば、エージェント的検索SDKとSaCエージェントスキルを、共通のオートリサーチループ内で共同で最適化することができます。より野心的な試みとしては、SDKとして公開された低レベルの検索プリミティブを利用できるようにモデルをトレーニングすることも考えられます。モデルトレーニングプロセス自体の中で、SDKの設計を共進化させることさえ可能かもしれません。今後の研究において、よりアグレッシブな共同設計戦略を追求することを楽しみにしています。
私たちは、モデルが検索結果を消費するだけでなく、検索プロセスを制御できるようにするためにSaCを構築しました。私たちの結果はこの制御の力を証明しています。SaCは、知識集約的なエージェントベンチマークにおいて、絶対的なパフォーマンスと費用対効果のフロンティアの両方を前進させます。今日からPerplexity ComputerとAgent APIでSaCの機能をユーザーに提供できることを嬉しく思います。ユーザー(および彼らにサービスを提供するエージェント)が可能な限り強力かつ効率的な検索機能を持てるよう、スタックのすべてのレイヤーにわたってSaCアーキテクチャを最適化し続けます。
引用
@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}
}