Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】"What 22 Days of Building AI Systems Taught Me: Grounding, Evals, and Control"

2026年09月18日に「Dev.to」が公開したITニュース「"What 22 Days of Building AI Systems Taught Me: Grounding, Evals, and Control"」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

AIシステム開発では、LLMを単なるチャットボットでなくソフトウェアの一部と捉え、明確な入力、動作の制約、監視、そして改善度を測る評価が重要だ。RAGや自動評価、制御されたツール連携の実践を通し、AIはステートレスで、会話履歴はアプリケーションで管理すると学んだ。

ITニュース解説

AIシステム構築の学習体験は、大規模言語モデル(LLM)に対する認識を大きく変えるものであった。当初はLLMを高度なチャットボットと捉え、難しいのは効果的なプロンプトの作成であると考えていたが、22日間の実践を通じて、LLMはより大規模なソフトウェアシステムの一部を構成する確率的なコンポーネントであるという理解に至った。つまり、実際に役立つAI機能を実現するには、明確な入力、制約された振る舞い、システムの挙動を監視する観測可能性、そして変更が改善か退化かを判断する手段といった、他の本番環境用ソフトウェアと同様の要件が必要であると認識を改めることになった。

この学習は、まず基礎理論の理解から始まった。トークン、コンテキストウィンドウ、温度設定、埋め込み、そしてTransformerアーキテクチャといった概念を学び、それらを自分の言葉で説明し、検証する作業を行った。この検証の過程で、自信を持って説明していたいくつかの点が実は誤りであったと判明した。例えば、RAG(Retrieval Augmented Generation:検索拡張生成)はプライバシーやローカル環境での実行のためだけでなく、モデルに大量の情報を一度に与えることなく、要求時に必要な情報だけを検索して提供するという、より直接的な目的があることを理解した。また、埋め込みと次のトークンを予測するメカニズムを混同していたことや、英語の1ワードが約1.33トークンであるというトークン数の正確な推定方法を誤っていたことにも気づかされた。これらの経験から、AIの概念は具体的な説明と検証可能な実験を経て初めて真に役立つものになるという重要な教訓を得た。

次に、Ollamaと小型のローカルモデルを用いて、APIの抽象的な概念を具体的なものとして捉える実践を行った。モデルがトークンごとに回答をストリーミングする様子は、レイテンシ(遅延)が単なる抽象的な指標ではなく、体感できる要素であることを実感させた。また、モデルに一度事実を伝え、その後に以前の会話を送らずに質問をすると、モデルはその事実を覚えていないという実験結果は、LLMが本質的にステートレス(状態を保持しない)であることを明確に示した。チャットアプリケーションが記憶を持っているように見えるのは、アプリケーション側でこれまでのメッセージを毎回モデルに送り返すことで会話履歴を管理しているためであり、モデル自体は現在のコンテキストウィンドウに含まれる情報しか知らない。この事実は、後のエージェントワークフローにおける会話メモリの管理方法にも影響を与えることになった。さらに、英語だけでなくコードやヒンディー語におけるトークン化の違いを測定し、言語や内容によってプロンプトサイズが異なり、それに伴ってレイテンシやコスト特性も変わることを確認した。

続いて、RAGシステムの構築に取り組んだ。まずはローカルの埋め込みモデルを用いたセマンティック検索を実装し、その検索機能と生成モデルを組み合わせた。キーワードマッチングではなく、ユーザーの質問を埋め込みベクトルに変換し、それを文書の埋め込みベクトルと比較してコサイン類似度で関連性の高い情報を探し出す手法である。ここで重要な制約として、クエリと文書の埋め込みには同じモデルを使用する必要があることを学んだ。異なるモデルで生成されたベクトルは互換性のない空間に存在するため、比較しても意味がないからである。自分の学習ノートを対象にRAGパイプラインを構築し、ノートを段落単位のチャンクに分割し、短すぎるチャンクや情報量の少ないチャンクをフィルタリングし、埋め込んで保存、質問に対して最も関連性の高いチャンクを検索し、それらのチャンクと質問を生成モデルに与えて回答を得るという一連の処理を実装した。このシステムは467個のチャンクをインデックス化したが、すぐにRAGの品質が単一のモデル品質の問題ではないことを教えてくれた。例えば、プログラミングにおける温度設定についての質問に対し、確率表に関するチャンクを検索してしまい、適切な推奨値に関する情報を見つけられないといった問題が発生した。これは生成モデルの性能だけでなく、システムが誤った証拠を検索してくる可能性もあることを示している。この問題に対処するため、ソースの追跡、類似度スコアの可視化、最低スコアのしきい値設定、ソースの重複排除、そして一つのファイルからのチャンク数の制限といった改善策を導入した。チャンク分割の粒度も重要なエンジニアリングパラメータであることが判明した。チャンクが大きすぎると意味が希薄になり、小さすぎると周囲の文脈が失われる。また、永続ストレージの重要性も認識した。ノートの埋め込みを毎回計算するのに数分かかっていたのが、一度キャッシュすれば1秒未満で読み込めるようになり、後にChromaDBのような専門のデータベースに置き換えることでさらに効率を向上させた。

生成モデルについては、ローカルの小型モデルからGroqがホストする高性能なモデルへ移行した。これにより、特に検索されたコンテキストが正しかったにもかかわらず、小型モデルではその情報をうまく利用できなかったような質問に対する応答品質が大幅に向上した。この経験は、「検索の回答」(システムが正しい証拠を見つけたか)と「生成の回答」(モデルがその証拠を忠実に、かつ明確に利用したか)という重要な区別を明確にした。これらはそれぞれ異なるデバッグパスを必要とする。いくら生成モデルが優れていても、検索されたコンテキストが欠落していたり不適切であれば、正しい回答は得られない。また、完璧な検索が常に忠実な回答を保証するわけでもない。さらに、モデルに回答と信頼度をJSON形式で出力するように要求することも実践した。構造化された出力は単に見やすいだけでなく、システムの次の段階で応答をルーティング、検証、保存、または拒否する際に、散文のテキストを解析する手間を省くことができるという実用的な利点がある。

「なんとなく動いているようだ」という感覚に頼る評価戦略では不十分であるという認識が、学習の転換点となった。20問からなるRAG評価ハーネスを導入したのである。各テストケースでは、質問、期待される回答の概念、そして期待されるソースファイルが定義されていた。評価ツールは、回答が一致しているか、そして正しいノートが実際に検索されたかの両方をチェックし、詳細な結果を記録した。80%のしきい値を下回ると失敗として終了する設定であった。最初の実行では、20問中1問しかパスせず、正答率はわずか5%であった。しかし、これは決して落胆する結果ではなかった。むしろ、これまで得られた中で最も信頼できる信号であった。この失敗は、手動での軽いテストでは見落としていた設定ミスを発見するきっかけとなった。具体的には、RAGとチャンク分割の説明の大部分を含む重要なノートが、除外リストに含まれていたことが判明した。問題解決のため、ソースレベルでの検索トレースを用いて原因を調査し、最初のチェックが厳しすぎたり緩すぎたりした期待値を調整し、適切なコンテンツを再インデックス化し、同じテストスイートを繰り返し実行した。最終的には20問中16問、80%の正答率を達成することができた。この数値は普遍的な品質スコアではなく、システムが本番環境に対応できることを意味するものでもないが、小さな明示的な質問セットに結びついたベースラインとなる。その価値は、次にプロンプトや検索方法、モデル、またはコーパスに変更を加える際に、直感ではなく、より有用な基準と比較できる点にある。

最後のフェーズでは、小規模なツール利用ワークフローを構築した。まず、最大8ステップの制限、停止条件、一時的な失敗に対するリトライロジック、そしてすべての決定を記録する構造化されたステップログを含む、決定論的なループから始めた。次に、llama-3.1-8b-instantを用いた実際のプランナーを組み込んだが、モデルが出力したテキストが直接任意のプログラムの動作につながることは許さなかった。プランナーは、「read_progress_files(進捗ファイルを読み込む)」「summarize_status(ステータスを要約する)」「check_git_status(Gitステータスを確認する)」「ask_clarification(明確化を求める)」という、定義された4つのアクションの中から1つだけを選択できるように制約した。選択されたアクションは、実行部が処理する。モデルが利用できない場合や、許可されていないアクションを返した場合には、決定論的なフォールバックプランナーが引き継ぐ仕組みも用意した。ワークフローは選択されたアクション、結果、プランナーのソース、リトライ回数を詳細にログに記録する。例えば、一時的なシミュレートされた失敗の場合、最終的な成功メッセージの裏に隠れることなく、アクションが2回目の試行で成功したという事実を記録する。各実行の終わりには、ステップの軌跡がタイムスタンプ付きのJSONとして永続化され、端末の出力が後でレビュー可能な成果物となる。最後に、プランナーが次のアクションを選択する際、以前の意図とアクションのペアを実際のチャットメッセージとして再利用した。これにより、モデルはステートレスのままであるが、アプリケーションが実行履歴を供給することで、プランナーにそれまでに実行されたステップのコンテキストを与えることができた。これは、元の安全対策を維持しつつ、プランナーに必要な情報を提供する方法である。

この一連の学習を通じて、AI機能に対する定義が大きく変化した。モデルは確かに必要不可欠な要素であるが、それ自体がシステム全体ではないという認識に至った。変化する情報やプライベートな情報に基づいて回答を生成する必要がある場合には、RAGを活用することが重要である。また、チャンク分割、ソース選択、モデルの振る舞いは、それぞれ独立してテスト可能な関心事として扱うべきである。多くのプロンプト変更を行う前に、まず評価セットを作成することの価値は大きい。たとえ完璧ではないベースラインであっても、それは貴重な証拠となる。モデルには狭く定義されたアクションスペースを与え、それをコードで厳格に強制し、重要なパスには決定論的なフォールバックを用意しておく必要がある。最終的な回答だけでなく、システムがその出力に至った意思決定パスをログに記録することが重要である。AIシステムでの失敗は、多くの場合、システムがどのように出力に到達したかにその兆候が現れるからである。そして、LLMの呼び出し自体は状態を保持しないため、会話履歴はアプリケーション側で明示的に管理しなければならない。

学習開始時には、LLMが何を予測するかを学ぶことから始めたが、このフェーズを終える頃には、LLMが保証できないこと、すなわち根拠のある知識、決定論的なツールの許可、メモリ、そして変更が期待する振る舞いを改善したという証明を、システムとして補完することに焦点を当てて構築するようになった。今後は、このワークフローをさらに強化するか、あるいはこれらのパターンを実際の製品における小さなAI機能に応用するかを検討している。後者の道が真のテストとなるだろう。なぜなら、制御されたデモは有用であるが、ユーザーワークフローこそが、システムの制約が正直に現れる場所だからである。

関連コンテンツ

関連IT用語