UKA-GYRE 開発記 ― 技術深掘り編 第5回
前回の記事:
この記事は「UKA-GYRE 開発記」 技術深掘り編 第5回(完結) です。
前の4回で個別に解説してきた技術要素を、最終回では俯瞰する。このシステムは何であり、何でないのか。
1. このシステムを一言で表すと
UKA-GYREを技術的に要約するなら、こうなる。
「検索」「制御」「学習」の3つのエンジンが連動して回る、自己改善型コメント生成基盤。
「RAGシステムです」と言えば嘘ではない。
だが、それだけでは本質の半分も伝わらない。
RAGは検索と生成を繋ぐ手法であり、UKA-GYREの構成要素の一つに過ぎない。
このシステムの本質は、3つのエンジンが噛み合って 使えば使うほど出力の精度が上がり続ける構造 を作っていることにある。
1つ目のエンジンが、最適な参考資料を 選ぶ。
2つ目のエンジンが、それをもとにコメントを 書く。
3つ目のエンジンが、評価を次週の知恵に 変える。
この3つが週次サイクルで回り続ける。
ドメインはパーソナルダイエット指導というニッチな領域だが、設計判断そのものは汎用的だ。
RAGを「使える」から「信頼できる」に引き上げるための技術と哲学が、この構造に詰まっている。
システムの根幹を理解すればいくらでも他のシステム開発領域で応用が利くのだ。
この記事では、4回にわたって個別に解説してきた技術要素を、1枚の「解剖図」として描き直す。
2. コメント生成 ―― クライアントデータからコメントが届くまで
まず、1回のコメント生成で何が起きているかを追う。
トレーナーが「生成」ボタンを押してから、A/B2案のコメントが画面に表示されるまでの、およそ30秒間の旅だ。
2.1. Step 1:クライアントデータの取り込み
起点は、クライアントの食事記録だ。
30日分の体重・摂取カロリー・タンパク質・脂質・炭水化物が、1枚のExcelに詰まっている。
システムはこのデータを取り込み、直近30日間のトレンドを算出する。
週ごとの平均値、曜日ごとの傾向、体重の変化方向。
「この人の生活リズム」が数字から浮かび上がる。
2.2. Step 2:内部ラベル変換
生の数値をそのままAIに渡すと、毎回異なる解釈が返ってくる(第1回で語った1,820kcal問題)。
そこで、全ての栄養素をルールベースで 離散ラベル に変換する。
- カロリー 1,820kcal(目標2,000kcal)→
カロリー:やや不足 - タンパク質 85g(目標90g)→
タンパク質:おおむね十分 - 体重 -0.3kg/週 →
体重トレンド:緩やかな減少
AIには生の数値 と このラベルの両方を渡す。
数値で具体性を、ラベルで判断の安定性を、同時に確保する。
2.3. Step 3:複合キーの生成と検索
内部ラベルの組み合わせから 複合キー を生成する。
減量×実行期×カロリー制御 のように、方針・フェーズ・戦略の3軸で「今この人が置かれている状況」を一意に特定する。
この複合キーがメタデータフィルタとなり、検索エンジンが起動する。
- ティアード検索 ―― 3条件一致 → 2条件 → 1条件と段階的に緩和
- ラベルブースト ―― 方針・フェーズ・戦略の一致度をスコアに乗算
- Dualクエリ ―― 複数のキーワードを分けて構築し、2つの観点で検索
5種類のArtifact(SSOT・GOLD・PATTERN・PITFALL・THOUGHT)から、「今、このクライアントの、この状況に最も適した参考資料」が選ばれる。
2.4. Step 4:7層プロンプトの構築
選ばれた参考資料が、7層プロンプトの第6層に注入される。
| 層 | 内容 | 役割 |
|---|---|---|
| 第1層 | システムプロンプト | AIの役割定義 |
| 第2層 | MBTIスタイル | 16タイプの語り口ルール |
| 第3層 | 適用戦略 | 戦略ガイドライン |
| 第4層 | 内部ラベル+エビデンス | 自動計算結果と判断基準 |
| 第5層 | クライアントデータ | 身体情報・食事データなどの整形済生データ |
| 第6層 | RAG参考資料 | 過去の成功・失敗事例など |
| 第7層 | 絶対原則 | フォーマット・禁止事項最終念押し |
先頭と末尾に重要な制約を配置する「サンドイッチ構造」で、AIの注意力の偏りに対処している。
2.5. Step 5:A/Bコメント生成 → トレーナーへ
同一プロンプトを 2つの異なるモデル に同時送信する。
それぞれが異なる表現・構成でコメントを生成し、A案・B案としてトレーナーの画面に並ぶ。
トレーナーはA案かB案を選び、必要に応じて手直しし、Good・Normal・Badで評価する。
この選択・編集・評価の全てが CaseLog として記録される。
ここまでが「1回のコメント生成」の全体像だ。
ボタン1つの裏側で、データ変換・検索・プロンプト構築・AI生成・人間の評価という5段階のパイプラインが動いている。
3. 1週間のサイクル ―― データはどう流れるか
個別の技術要素は第1〜4回で解説した。
この最終回では、個別記事ではできなかった視点 ―― データが3つのエンジンをどう流れるか を、1週間のサイクルとして描く。
3.1. 月曜〜土曜:検索エンジンと制御エンジンが動く
トレーナーがコメント生成をリクエストする。
その瞬間、2つのエンジンが連動する。
検索エンジン がまず動く。
クライアントの食事データから内部ラベルを機械的に算出し、複合キーを生成する。
ティアード検索がメタデータフィルタで候補を絞り、ラベルブーストが状況の一致度をスコアに乗算し、Dualクエリが異なる観点から参考資料を引き当てる。
5種類のArtifactから、「今、このクライアントの、この状況に最も適した参考資料」が選ばれる。
制御エンジン がその参考資料を受け取る。
7層プロンプトに注入し、MBTIスタイルで出力を制約し、temperature=1.0の揺らぎの中でA/B2案のコメントを生成する。
トレーナーがA案かB案を選び、Good・Normal・Badで評価する。
この選択と評価がCaseLogに記録される。
月曜から土曜まで、このサイクルが毎日回る。
CaseLogには1週間分の「どのモデルの、どの表現が、どの状況で選ばれたか」が蓄積されていく。
3.2. 日曜深夜:学習エンジンが目を覚ます
日曜深夜、EventBridgeが昇華バッチを起動する。
1週間分のCaseLogが入力だ。
Good評価からはGOLD(お手本)とPATTERN(成功パターン)が生まれる。
Normal評価からはPATTERN(成功パターン)が生まれる。
Bad評価からはPITFALL(失敗の教訓)が生まれる。
トレーナーのメモからはTHOUGHT(知見)が生まれる。
品質フィルタがゴミを弾き、AI出力フォーマットが構造を統一する。
生成された知恵はS3に格納され、Amazon Bedrock KBのIngestion Jobがベクトルインデックスを更新する。
1時間後、退役バッチが起動する。
使われなくなった古い知識を退役させ、ナレッジベースの密度を維持する。
増やすだけでは堆積するだけだ。増やしながら削ることで、蓄積になる。
3.3. 翌週月曜:螺旋が一段上がる
翌週月曜、トレーナーがコメント生成をリクエストする。
検索エンジンがナレッジベースを検索するとき、先週はなかった新しいArtifactがヒットする。
先週の成功パターンが今週の参考資料になり、先週の失敗の教訓が今週の地雷回避になる。
1週目と10週目のAIは別物だ。
同じコード、同じモデル、同じプロンプト構造。
変わったのはナレッジベースの中身だけ。
しかしその差が、コメントの品質を決定的に変える。
4. この設計を貫く4つの哲学
3つのエンジンの背後には、設計判断を貫く哲学がある。
各記事の結びで語ったものを、ここで「システム全体にどう波及しているか」の視点で統合する。
4.1. 哲学1:AIに判断させない(第1回)
第1回で語った1,820kcal問題。AIに数値を渡したら毎回違う判断が返ってきた。
この原体験から生まれた哲学が、システム全体のアーキテクチャを決定づけた。
AIの役割を「文章の生成」に限定し、「状況の判断」はさせない。
カロリーも、タンパク質も、体重トレンドも、全てルールベースで離散ラベルに変換してからAIに渡す。
この哲学は検索エンジンにも波及している。
「どの過去事例を参考にすべきか」もAIには選ばせない。
ティアード検索とラベルブーストが機械的に選定し、結果だけをAIに渡す。
メタデータフィルタリングの複合キーは、この「判断させない」哲学の最終形態だ。
AIに何をさせないかを決めることが、AIに何をさせるかを決めることより重要だった。
4.2. 哲学2:妥協を設計する(第2回)
第2回で語った「100%の検索精度は存在しない」という絶望。
その絶望を受け入れた日に、問いが変わった。
ティアード検索は「妥協を設計する」の実装だ。
全条件一致が見つからなければ条件を緩和し、それでも足りなければさらに緩和する。
「最善が無理なら次善を」という段階的な妥協がコードとして明文化されている。
この思想は検索エンジンだけでなく、学習エンジンにも波及している。
品質フィルタでは「まだ評価されていない新しいデータは、ひとまず通す」という寛容さと、「事例が十分に集まるまではパターン化しない」という慎重さを両立させている。
完璧を求めず、しかし最低ラインは守る。その線引きをコードに書く。
4.3. 哲学3:変更可能性を最大化する(第3回)
第3回で語ったtemperature=0.6→1.0の転換。プロンプトの1行を変えただけで振る舞いが劇的に変わる世界で、正解は理論からではなく実験から見つかる。
S3ベースの動的設定管理は、この実験駆動を支える基盤だ。
プロンプト、MBTIスタイル定義、推論パラメータ。全てがS3上のファイルとして管理され、Lambda再デプロイなしに反映される。
この思想は制御エンジンだけでなく、システム全体に波及している。
学習エンジンの昇華バッチも、出力フォーマットや品質基準をコードではなく設定で管理している。
検索エンジンのブースト値もチューニング可能だ。
変えるコストが低ければ実験の回数が増え、実験の回数が増えれば正解に近づける。
4.4. 哲学4:自分がいなくても動き続けること(第4回)
第4回で語った「個人開発の最大のリスクは自分が単一障害点になること」。
自分が寝ている間も、旅行中も、体調を崩しても、システムは止まらない。
昇華バッチは日曜深夜に勝手に回り、退役バッチはその1時間後に勝手に掃除する。
この哲学はインフラだけでなく、3つのエンジン全体の設計を規定している。
- 検索エンジン は人間のチューニングなしに自律的にスコアを計算する
- 制御エンジン はS3の設定ファイルから自動ロードする
- 学習エンジン はEventBridgeが勝手に起動し、勝手に終わる
この設計を選んだ一番の理由はコストではない。自分を運用から外すためだ。
5. 設計判断は最初から正しくはならない
4回分の技術記事を書いてきたが、設計判断が最初から正しかったことは一度もない。
全て、失敗して、原因を特定して、修正した結果だ。
面白いのは、この「失敗→学習→改善」のサイクルが、UKA-GYREの自己改善ループそのものと同じ構造だということだ。
システムがトレーナーの評価から学んで賢くなるように、開発者も痛みから学んで設計を磨いてきた。
設計判断は最初から正しくはならない。でも、失敗から学んで修正する仕組みがあれば、システムは確実に良くなる。
6. 数字で見るUKA-GYRE
このシステムの規模感を数字で示す。
| カテゴリ | 数値 |
|---|---|
| バックエンドコード | 約49,000行 / 117ファイル(TypeScript) |
| フロントエンドコード | 約15,000行 / 80ファイル(TypeScript / React) |
| インフラコード | 約2,600行 / 8スタック(CDK TypeScript) |
| APIルート | 約50 |
| Lambda関数 | 4(コメント生成、API、昇華バッチ、退役バッチ) |
| サービスクラス | 28 |
| AWS SDKラッパー | 7(S3、DynamoDB、Amazon Bedrock、Cognito等) |
| Next.jsページ | 14 |
| DynamoDBテーブル | 8 |
| Artifact種別 | 5(基本ルール、お手本、成功パターン、失敗パターン、知見メモ) |
| MBTIスタイル | 16パターン |
| プロンプト層 | 7層 |
| 月間運用コスト | $40〜150 |
| 開発期間 | 3ヶ月以上(企画〜商用運用) |
約66,000行のTypeScriptが、月$40〜150で商用運用されている。
ただし、この数字だけを見て「個人開発でもこのくらい作れるのか」と思ってほしくはない。
動くプロトタイプは2週間で作れた。
しかしそこから商用運用に耐えるレベルに引き上げるのに2ヶ月以上を費やした。
エラーハンドリング、品質フィルタ、退役バッチ、プロンプトチューニング。
プロトタイプが全工程の20%に過ぎなかったという現実は、コード量よりも雄弁にこのプロジェクトの難しさを語っている。
7. 最後に:このシステムが証明したこと
5回にわたる技術深掘りを終える。
UKA-GYREの開発を通して証明されたことが、3つある。
第一に、個人開発でも商用RAGシステムは構築可能だ。
S3 Vectors、Amazon Bedrock Knowledge Bases、DynamoDB On-Demand。
2025年以降のAWSマネージドサービスの進化は、OpenSearch Serverlessの固定費とVPCの運用負荷という2つの壁を取り払った。
かつては企業の予算と運用チームがなければ不可能だったRAGシステムが、個人の手で作れる時代になった。
第二に、RAGの品質は「検索と生成のあいだ」で決まる。
ベクトル検索を導入した。
プロンプトを書いた。
それだけでは「まあまあのRAG」しかできない。
ティアード検索、ラベルブースト、内部ラベル、Dualクエリ、品質フィルタ。
検索結果をプロンプトに渡すまでの「あいだ」に何層もの補正と選別を挟むことで、はじめて「信頼できるRAG」になった。
この「あいだ」のエンジニアリングこそが、RAGシステムの競争力そのものだ。
第三に、自己改善ループは設計できる。
「使えば使うほど賢くなる」は魔法ではない。
昇華バッチで知恵を蓄積し、品質フィルタでゴミを除き、退役バッチで古い知識を淘汰する。
このサイクルを設計し、コードに落とし込み、毎週日曜の深夜に確実に回す。
自己改善は意思ではなく、仕組みだ。
このシステムは完成していない。
おそらく、永遠に完成しない。
検索エンジンのブースト値は来月も微調整されるだろう。
プロンプトの文言は来週も書き換えられるだろう。
昇華バッチが生成するArtifactの品質は、評価データが増えるほど上がり続けるだろう。
「完成しないこと」はシステムの欠陥ではない。
自己改善を前提として設計されたシステムが「完成する」ことは、改善が止まることを意味する。
それこそがこのシステムの死だ。
螺旋は回り続ける。
プロローグから数えて全12回。
ここまで読んでくださった方に、心から感謝を。
RAGって面白そうだな。
プロンプトって思ったより奥が深いんだな。
自分でも何か作ってみたいな。
エンジニアの方にも、そうでない方にも、この開発記が何かひとつでも残せていたら、書いた甲斐があった。
ありがとうございました。
コラム:プログラマーが「調教師」になる日
これまでのソフトウェア開発は、完璧な「ルール」を書く作業だった。
「もしAが起きたら、Bをしろ」を何万行も積み上げる。これが ソフトウェア1.0 だ。AI時代のプログラマーは、ルールを書かない。代わりに「結果」を教え込む。
「心に響く文章とは何か」を論理式で定義するのは不可能だ。
しかし「こっちのほうが良い」「こっちはダメ」を繰り返し示すことで、AI自身にその法則を掴ませることはできる。
これが ソフトウェア2.0 ―― ルールを書くのではなく、価値観を育てるプログラミングだ。それは設計というより、調教に近い。
UKA-GYREの運用で、AIが生成したA案とB案をひたすら見比べて「こっちがいい」と選び続けた日々。
あれは単なる運用作業ではなく、ソフトウェア2.0の最前線にいたのだと、今なら分かる。だから私は、このシステムを「作った」のではなく「一緒に育てた」と感じている。
「UKA-GYRE」開発記 シリーズ目次
読み物編 --- エンジニアでなくても楽しめる!
- プロローグ ― UKA-GYRE 開発記
- 読み物 第1回 ― ISTJには数字を、ENFPには共感を ― AIに「性格」を与えた日
- 読み物 第2回 ― 深夜3時はAIの経験値稼ぎタイム ― 「昇華」のメカニズム
- 読み物 第3回 ― カロリーの数字の裏にある物語 ― AIが「今日のあなた」を理解するまで
- 読み物 第4回 ― 「何を書くか」より「どう伝えるか」 ― AIを使った大人の実験科学
- 読み物 第5回 ― 「AIが書いた」ではなく「AIと一緒に書いた」 ― Human-in-the-Loopという思想(完結)
- 読み物 番外 ― 自分が作ったAIに食べ過ぎを怒られ続けた話 ― 開発者の裏側
技術深掘り編 --- 設計判断と実装の詳細
