Rustで構築されたAIアプリケーションは、JetBrainsがRust Foundationと共同で実施したライブデモによれば、初期の実験段階から徐々に、より実用的な形態へと移行しています。最初のセッションでは、オープンソースライブラリであるRigと、大規模言語モデルを利用し、ツールを呼び出してアプリケーション内でタスクを実行できるエージェントベースのアプリケーションを構築する方法に焦点が当てられました。
Developer AdvocateのOrhun Parmaksızは、RigとRatatuiを使って構築した小規模なコーディングエージェントを実演しました。一方、0xPlaygroundsでRigを主に担当するStephen Korzeniewskiは、プロジェクトの内部構造と、そのAPIの背後にある設計上の選択について説明しました。
モデルプロバイダー向けの統一インターフェース
Rigは、大規模言語モデルアプリケーションにおける一般的な実務上の問題に対処します。OpenAI、Anthropic、Geminiなどはそれぞれ異なるAPIを提供しており、一部のサービスがOpenAI APIとの互換性をうたっている場合でも、その違いは残ります。アプリケーションの各部分を単一のプロバイダーのAPIに直接結び付ける代わりに、Rigは統一されたRustインターフェースを提供し、モデルに関連する部分を書き直すことなくプロバイダーを切り替えられるようにします。
このライブラリでは、プロバイダーのクライアント、補完モデル、エージェント、エージェントが利用できるツールなど、複数の基本コンポーネントを中心にアプリケーションを構成します。エージェントはモデルへの直接的なリクエストより上位のレイヤーとして動作し、入力テキストと出力テキストの単純な流れを超えるタスクを実行するために必要な指示、トークン制限、機能を追加します。
エージェントへの指示は、Rigがpreambleと呼ぶものに渡されます。これはシステムプロンプトの役割を果たす指示で、各リクエストの冒頭に挿入されます。モデルプロバイダーとのネットワーク通信は非同期インターフェースを通じて管理されますが、非同期処理の詳細の多くはライブラリ内部に保持されるため、アプリケーションコードは必要な設定と動作に集中できます。
ツールによってエージェントがアプリケーションの一部になる
Rigでは、RustのTool traitを通じてツールを定義します。ツールの定義には、名前、入力・出力・エラーの型、呼び出されたときに実行される関数が含まれます。また、JSON Schemaを使って想定される引数を記述するため、モデルは提供可能なデータについて構造化された説明を受け取れます。
エージェントにツールを登録すると、ツール呼び出しに対応したモデルは、いつツールを使うかを判断し、その結果を応答に組み込めるようになります。関数は、計算を実行したり、データベースに問い合わせたり、情報を取得したり、別のサービスに接続したりできます。ツールは、呼び出し回数やキャッシュされた結果などの状態を保持するコンテキストを受け取ることもできます。この考え方はエージェント自体にも拡張でき、あるエージェントを別のエージェントのツールとして公開して、相互にタスクを委任できます。
実演からテスト可能なアプリケーションへ
Rat Codeプロジェクトは、これらのコンポーネントをRigとRatatuiを使う、ターミナル上で動作する小規模なコーディングエージェントにまとめています。main.rsファイルではプロバイダーのクライアント、モデル、エージェントを初期化します。一方、ファイルの読み書きやシェルコマンドの実行機能は別々に定義され、Rigのツールインターフェースを通じてエージェントに登録されます。
このアプリケーションはRigのストリーミングインターフェースも使用し、応答をチャンク単位で処理して、モデルが回答を生成している間にターミナルのUIを更新します。実演では、フックのシステム、ツール呼び出しからの復旧メカニズム、そしてライブラリが提供する抽象化の背後にある設計上の選択についても扱われました。完全なコードの解説は、録画の27:28から始まります。
RAG、ローカルモデル、テスト
Rigはホスト型モデルのプロバイダーだけに対応しているわけではありません。文書やユーザーのクエリをベクトル埋め込みに変換し、意味的に最も近い文書を検索してモデルのコンテキストに追加する、検索拡張生成にも対応しています。ライブラリはデータベースとの統合やベクトルストアの抽象化を提供しており、直接サポートされていないデータベースを使う場合には、ベクトルストアのインターフェースを実装できます。
また、Ollamaやllama.cppを通じてローカルモデルを実行したり、rig-candle統合を使ってRustアプリケーション内で直接推論を実行したりできます。この選択肢では、モデルの重みをアプリケーションに組み込み、ホスト型モデルのAPIや別個のローカル推論サーバーに依存せずに、WebAssemblyでサポートされるモデルを実行できます。
モデルとデータをどこで実行するかという点で、これらの選択肢は重要です。しかし同時に、統合テストという課題も生じます。Rigは主に記録システムに依存しています。実際のプロバイダーを使ってテストを実行し、HTTP通信をYAMLファイルに保存した後、モックサーバーが継続的インテグレーションのテスト内でリクエストとレスポンスを再生します。プロジェクトには約1,700件の記録済みインタラクションが含まれており、各プルリクエストのたびに、これらのインタラクションが数秒以内に再実行されます。
これらのテストはソフトウェア統合が引き続き機能することを検証しますが、モデルプロバイダーがモデルを更新した際に変化する可能性がある、モデル出力の品質は測定しません。そのため実演では、回答品質に依存するアプリケーション向けに、稼働中のモデルに対するスケジュール実行テストが別の手法として紹介されました。
編集部による考察:開発者にとって重要な点とは?
Rigの実務上の価値は、単に新しいプロバイダーを追加できることではありません。アプリケーション層をモデルAPIの詳細から切り離しながら、ツール、検索、ローカル推論を単一のRustアーキテクチャ内に維持できる点にあります。これにより、プロバイダーや実行方法を変更するコストを削減できる可能性がありますが、モデル間の動作上の違いをなくすものではなく、出力品質の評価問題を単独で解決するものでもありません。プロジェクトのテスト機構が示しているように、接続が機能することを保証することと、モデルが期待した結果を生成することを確認することは別の問題であり、後者には実稼働モデルを使ったテストと独立した評価基準が必要です。