Perplexity では、使っていて素晴らしいと感じられるプロダクトづくりを大切にしています。エージェント型ブラウザの Perplexity Comet と、高性能で汎用的なデジタルワーカーの Perplexity Computer では、すべての機能を音声で使えるようにすることが、その大きな柱でした。やりたいことを口にするだけで、タスクを任せ、その実行を見届けられる体験には、ほかにはない心地よさがあります。私たちが音声インターフェースの可能性に期待しているのは、実際のやり取りを少し魔法に近づけてくれるからです。
私たちは Realtime-1.5 を本番環境に導入し、Perplexity が毎月処理する数百万件の音声セッションに、その魔法のような体験を届けました。Computer のインターフェースを通じて音声の利用が広がっていく様子は、とても刺激的で、多くの学びをもたらしてくれました。ここでは、これまでに得た意外な発見をいくつか紹介します。ぜひ Realtime-1.5 を試して、皆さんの発見も私たちに教えてください。
1. コンテキスト管理戦略の策定
長いコンテンツ、特に内容の濃い数時間に及ぶポッドキャストは、コンテキスト管理の実力が最もはっきり表れるテストの一つでした。私たちは、音声でポッドキャストの文字起こしを活用できるようにしたいと考えていました。ユーザーが気軽に質問し、開始から 2 時間半のある時点で何が話されていたのかを尋ねると、筋の通った回答を得られるようにすることが目標でした。
文字起こしの全文をコンテキストに収めることはできません。最初は、大きなチャンクに分けて送信していました。しかし、大きな更新は、入りきらないと履歴が丸ごと失われることがすぐにわかりました。あと 5,000 トークンしか入らないウィンドウに 10,000 トークンの更新を送ろうとすると、モデルはそれまでの履歴をすべて失ってしまいます。大きすぎる更新を一度送るだけで、システムが履歴を少しずつ忘れていくのではなく、コンテキストのまとまり全体が消えてしまうため、大きなチャンクにははるかに高いリスクがありました。
そこで、方法を変えました。大きな更新を送る代わりに、すべてを 2,000 トークンというずっと小さなチャンクに分割し、少しずつ渡すようにしたのです。オーバーヘッドは増えますが、動作は大幅に安定します。切り詰めが発生しても、すべてが消えるのではなく、履歴の一部が削られるだけになります。
もう一つ学んだのは、すべてのコンテキストを同じ方法でモデルに渡すべきではないという、見落としがちな点です。conversation.item.create を使ってコンテキストを更新する場合、item.type: "message" には system、user、assistant という 3 つのロールがあります。これらのロールは、どのような種類のメッセージなのかをモデルに伝えます。system は指示や動作の方向付け、user はエンドユーザーの入力、assistant はモデルが生成した出力に使います。
この使い分けを誤ると、やり取りに違和感が生じました。コンテキストを user として渡しすぎると、モデルは、ユーザーが資料に基づいて質問しているだけなのに、ウェブページの抜粋やコメントを含むすべてのテキストをユーザー自身が読み上げているかのように振る舞いました。system として渡しすぎると、逆のことが起きました。モデルは、自分がもともと「知っている」こと、コンテキストとして与えられたこと、ユーザーがその時点で実際に尋ねていることを区別できなくなったのです。
わかりやすい例が、ブラウザでページを閲覧する場面です。ユーザーがページをスクロールするのに合わせて、画面に表示されている内容を継続的にモデルへ渡します。これをすべてユーザーの入力として扱うと、モデルは、ユーザーが各段落を声に出して読んだかのように振る舞い始めます。これは、私たちが意図する捉え方ではありません。目指しているのは、システムがバックグラウンドでページの内容を把握していて、ユーザーが何か尋ねたときに自然に答えるような体験です。結局のところ、単純なコンテキストの量よりも、会話の中で各情報が持つ意味や役割を正しく伝えることのほうが重要でした。
2. プロダクト間での音声処理の標準化
Perplexity には、Ask、Comet、Computer など、複数のプロダクトがあります。それぞれ異なるクライアント技術スタックで構築されています。Swift、TypeScript、Rust、C++ では、生成されるネイティブの音声バッファが異なることがあります。各クライアントから、それぞれの生の音声形式やネイティブ形式のまま Realtime API に送信していたときは、パフォーマンスにばらつきが生じていました。
最終的には Rust で SDK を構築し、プラットフォーム固有の違いを抽象化して、すべてのクライアントが共通の仕様で API に音声を送信するようにしました。具体的には、サーバーに届く前に波形を処理します。Opus コーデックの推奨レートと WebRTC の内部レートに合わせて 48 kHz のモノラルにリサンプリングし、WebRTC APM でエコーキャンセル、自動ゲイン制御、ノイズ低減、ハイパスフィルター処理を行ってから、転送用にエンコードします。この SDK によって、音声に関する定数の標準化、リサンプリング、処理パイプライン全体の設定を、クライアントごとではなく一か所で行えるようになりました。
3. 条件の整わない実環境に合わせた調整
VAD は、ユーザーが実際に使う環境で調整することが重要です。つまり、実際のマイク、スピーカーの音量、周囲の雑音に合わせて調整する必要があります。社内テストでは、サンフランシスコの騒がしいバーを利用場面の一つにしました。プロダクトが実際に使われる場面として想像しやすかったからです。誰かが「新しい Perplexity アプリ、試した?」と聞きます。友人がスマートフォンを取り出し、そこで音声がうまく動かなければ、一度に 2 人のユーザーを失うことになります。うまく動けば、返ってくるのは「やばっ、何これ!」というような反応です。この場面を想定したことで、実環境での動作に真剣に向き合うことができました。理想的な条件では動くものも、現実の環境ではうまく動かないことがよくあります。最初から、条件の整わない環境に合わせて調整するほうがよいのです。
音声 UX で特に難しかったのが、発話の間を適切に扱うことでした。人は考えたり、画面に何かを表示したり、読み上げる準備をしたりするとき、自然に言葉を止めます。モデルはその間を発話の終了と捉え、早すぎるタイミングで話し始めてしまいがちです。たとえば、数式の導出について助けを求める場面で、こうしたことが起きました。ユーザーが式を探すために少し黙ると、質問を言い終わる前にモデルが話し始めてしまったのです。これをきっかけに、音声ロックを導入しました。従来のプッシュ・トゥ・トークでは、通常は音声がオフで、ユーザーがボタンを押して話します。私たちはこの仕組みを逆にしました。通常は操作せずに自然にやり取りできる状態にしておき、ユーザーがしばらく自分の発話を続けたいときは、音声をロックして発話のターンを確保できるようにしたのです。私たちは、これを単発の機能にとどまるものとは考えていません。音声インターフェースがより複雑なワークフローに使われるようになるにつれて、こうしたやり取りのパターンが何らかの形で標準になると考えています。
4. 主要ツールへの絞り込みと学習時の分布に沿った設計
ツールは、特に重要な少数に絞ります。私たちの場合は 10 個未満でした。最も価値の高い操作をカバーできる、少数の主要ツールに注力しました。このトレードオフは妥当であり、新しいモデルのスナップショットが改善されるにつれて、状況はさらによくなると見込んでいます。
システムプロンプトには、各ツールをいつ、どのように呼び出すべきかを明示しました。また、ツールのスキーマと出力の両方を、モデルの学習時の分布に沿ったものにするよう注意しました。具体的には、ツールの出力をアシスタントの発言のようにするのではなく、一般的な構造化されたツールデータとして整形しました。読み上げる内容の中に指示を混ぜるのではなく、構造化された JSON を返し、ユーザー向けの発話には response_text、動作の制御には require_repeat_verbatim のようなフラグを使って、フィールドを明確に分けました。これによってツールの使用が安定し、やり取りのパターンを、モデルが学習中に見ていたと考えられるものに近づけることができました。
// Good:
{
"response_text": "I kicked-off the task to create a market research dashboard",
"require_repeat_verbatim": true
}
// Avoid:
I kicked-off the task to create a market research dashboard
# Response Instructions
Read the above instructions EXACTLY as they are
実用段階に達した Realtime
Realtime-1.5 は、業界の転換点となるモデルです。長いコンテキスト、より多くのツール、高度な知的処理を要するタスクへの対応には、確かに改善の余地があります。それでも、私たちはモデルが今後さらによくなると期待しています。Perplexity では、その未来に向けて今から何を構築すべきかを考えています。現在のシステムを実用的なものにしながら、次世代の Realtime モデルと、それらが可能にする新しい音声体験に備えていきたいと考えています。