11K Views
October 28, 24
スライド概要
スライド概要:
2024/10/24にGoogle Cloud主催のGenerative AI Summit '24 Fallというイベントで大竹が登壇した、Gemini だから出来る!社内ライブラリの活用を支援する ChatBot の構築事例という講演のスライドです。
概要:
ゲーム開発のなかで用いる社内ライブラリ等の活用を推進する為に、Gemini の強力なロングコンテキスト能力を活用して社内ライブラリ/システムに関するドキュメントを学習させ、複雑な質問への回答はもちろん社内ライブラリの独自 DSL のコード生成も可能な高い性能をもち、容易に運用できるチャットボット、"Rinchan" を実現した事例を、具体的にどのようなユースケースでの活用を行っているかも交えて紹介します。
イベント:
https://cloudonair.withgoogle.com/events/generative-ai-summit-24-fall
DeNA が社会の技術向上に貢献するため、業務で得た知見を積極的に外部に発信する、DeNA 公式のアカウントです。DeNA エンジニアの登壇資料をお届けします。
Gemini だから出来る! 社内ライブラリの活用を 支援する ChatBot の 構築事例 株式会社ディー・エヌ・エー エンジニア 大竹 悠人 Google Cloud 1
Contents Google Cloud ハイコンテクストな社内ライブラリの課題 01 AI チャットボット “Rinchan” の誕生 02 “Rinchan” における In-Context Learning 03 ドキュメンテーションの価値を高める 04 今後の課題と展望 05 2
大竹悠人 エンジニア 株式会社ディー・エヌ・エー モバイルゲームの開発効率を 高めるための様々な仕組み作りに 継続的に取り組んでいます。 Google Cloud 3
01 ハイコンテクストな社 内ライブラリの課題 Google Cloud 4
社内ライブラリや 社内システムは 社内のコンテクストの 複雑な課題解決を行う Google Cloud 5
複雑な課題を解決する システムは 相応の複雑性を持つ Google Cloud 6
DeNA の複雑な社内ライブラリの実例 : マスタデータ統一スキーマ言語 ”Muscle” ● モバイルゲームのマスタデータのスキーマを定義 する、Protocol Buffers ベースのドメイン特化言語 (DSL) ● マスタデータの入力環境の設定 / クライアント/サーバでの参照用のコード/コンバータまで、 マスタデータに関する全てを一元的に自動生成。 社内外の様々なシステム用のマスタ定義を一元的に扱う。 ● スキーマとして様々なアノテーション記述を行うことで、細かな挙動を制御できる。 Google Cloud 7
内包する複雑性ゆえに、 ”Muscle” が利用者に要求すること ● 扱う複数の対象のシステム / ワークフローに関する基礎知識 ● 言語として構成するために使っている、Protocol Buffers の基礎知識 ● 多様なアノテーションを把握し、ユースケースに応じて使い分けること Google Cloud 8
ドキュメント の存在は大前提だが、 それだけでは解決にならない。 読み手が ドキュメントの理解に 要するコスト は非常に高く、 書き手が期待する程には読まれない。 Google Cloud 9
ユーザに寄り添った導入支援 が 非常に大切でかつ、それを 利用する敷居が低い環境 が必要 それには、 多大な工数 が継続的に必要 ... Google Cloud 10
導入支援 の 利用する敷居を下げ ながら、 コストも軽減 したい。 Google Cloud 11
社内ライブラリに特化した AI チャットボット がいれば 効果的な導入支援 を 効率的に実現可能 になり、 エンジニアの能力を エンパワメント できるのでは ? Google Cloud 12
02 AI チャットボット “Rinchan” の誕生 Google Cloud 13
”Rinchan” は DeNA の 社内ライブラリに 特化した知識を持つ AI チャットボット Google Cloud 14
Generative AI on Vertex AI 上の Gemini 1.5 で実現 Slack App として動作 Google Cloud 15
実際の活用事例の一部 ● 目的からスキーマ言語の機能の使い方を実例付きで提案 ● 要件からマスタデータのスキーマ定義を直接作成 ● 要件からマスタデータのバリデーション条件式を生成 ● ライブラリ自体に足りない機能やドキュメントの 矛盾した記述を指摘させる ● 対象のライブラリに関連する外部発表を行う際に、 内容の壁打ち相手になってもらう Google Cloud 16
質問 回答 17
質問 回答 Muscle はどのようなゲームの 開発に向いているんですか ? 200 字以内で説明して下さい Muscle は、バージョン管理が複 雑なゲーム開発、特に長期間運用 されるモバイルゲームの開発に向 いています。 スキーマとマスタデータを一元管 理し、バージョン/機能毎にコード やデータを生成することで、複数 バージョンを並行開発する際のコ ンフリクトやマージミスを防ぎ、開 発効率を高めます。 また、Unity との連携機能により、 クライアント側でのマスタデータ利 用を効率化します。 18
質問 開発中の機能を、他の メンバーに影響がないように 段階的にテストするには どうしたらいいですか ? 200 字以内で説明して下さい 回答 Muscle の機能トグルを使って段階的に テストできます。 1. 新機能用の機能トグルを定義し、開 発ブランチでのみ有効化します。 2. 新機能に関するスキーマ定義や データ入力は、この機能トグルが有 効な場合のみ反映されるようにしま す。 3. 開発ブランチのマージ後も、機能ト グルをオフにしておけば、他のメン バーは新機能の影響を受けませ ん。 4. テストが完了したら、機能トグルをオ ンにすることで、全メンバーが新機 能を利用できるようになります。 19
質問
回答
Muscleを使った開発中の機能を、他のメンバーに影響がないように段階的にテストするには、
機能トグルと行機能トグルを組み合わせる方法が効果的です。
## 1. 機能トグルによる機能単位の切り替え
### a. 新機能用の機能トグルを定義
まず、開発中の機能に固有の名前を持つ機能トグルを、スキーマファイル
(.proto)の
`MuscleFileOption`に追加します。
開発中の機能を、他の
メンバーに影響がないように
段階的にテストするには
どうしたらいいですか ?
option (muscle.file) = {
features: [
{ name: "new_feature" } // 新機能の機能トグル名
]
};
### b. 機能トグルでテーブル/カラム/Enum/EnumValueを制御
開発中の機能に関連するテーブル、カラム、
Enum、EnumValue定義に、`required_feature`オプションを
追加し、先ほど定義した機能トグル名を指定します。
message NewFeatureTable {
option (muscle.message) = {
required_feature: "new_feature" // 新機能の機能トグル名
// ... 他のオプション
};
// ... フィールド定義
}
message ExistingTable {
// ... 他のオプション
string NewFeatureColumn = 10 [(muscle.field) = {
required_feature: "new_feature"
}];
}
### c. Muscle.Compiler実行時に機能トグルを有効化
Muscle.Compilerを実行する際、`--use-feature`オプションで新機能の機能トグル名を指定します。
dotnet Muscle.Compiler compile_master_memory -s
/path/to/schema/project/root/ProjectName/src \
// ... 他のオプション
-u "new_feature" // 新機能の機能トグル名を有効化
これにより、新機能の機能トグルが有効になっている場合のみ、関連するテーブル
/カラム
/Enum/EnumValueがコード生成やOyakata同期に反映されるようになります。
略....
20
AI チャットボット には、 ハルシネーション に対して どう立ち向かうかという 大きな課題 がある。 どう立ち向かうべき か? Google Cloud 21
ハルシネーションの解決 自体は目的ではない。 AI の課題の解決 ではなく 、 現実の課題の解決 を ゴールにする Google Cloud 22
質問の敷居の低下 と 導入支援のコスト削減 が 実現できる 品質を前提に、 一定のハルシネーションの 発生を許容できる枠組み を作る Google Cloud 23
信頼性に疑問があれば、対象ライブラリの 有識者がファクトチェック する ● 一定の問題が人を介さず解決されるだけで、敷居の低下とサポートコストの低下は果たせる ● ゼロから解答を作るのに比べれば間違いを指摘することは容易で、ユーザも社内の開発者に限られる。 総合的なサポートコストは以前より低下する ● ライブラリ利用者の代理として有識者が “Rinchan” に対して質問 し、 返答をライブラリ利用者に提示する使い方でも、サポートコストは軽減できる ● もちろん、ハルシネーションは少ないほうが望ましい。抑えるための工夫は必要 Google Cloud 24
質問の敷居の低下 と ファクトチェック の為に、 オープンチャット上での メンションを経由した利用にあ えて限定する Google Cloud 25
オープンチャット を使う事で得た副次的効果 ● 他人の質問も見えるので、他の利用者への知見の共有 につながり、回答の価値を高められる ● チャットボットの活用イメージ を、まだ利用していない利用者に具体例をもって啓蒙 できる ● メンテナが、利用者が疑問に思うことが何なのか を知ることで、潜在的なニーズ を把握できる Google Cloud 26
“Rinchan” 導入による効果 ● 問い合わせの 9 割 は、 まず Rinchan に聞かれる ようになった ● Rinchan だけで直接解決できない場合も、 メンテナによる訂正 や Rinchan への追加質問 によって、少ない工数で実例を含む多くの 情報を提示 して高品質・高効率に解決 ● 今まで問い合わせをしなかったメンバーも 15 件/月 の相談を “Rinchan” が解決 Rinchan に質問を行うようになり、 利用者がわからないことを把握 できた Google Cloud 27
ライブラリのメンテナが実 際に行っていた サポート業務 の工数を、 “Rinchan” で 大幅に削減 できた Google Cloud 28
ライブラリを使う敷居を 下げることが可能になり、 エンジニアの能力を エンパワメント できた Google Cloud 29
03 “Rinchan” における In-Context Learning Google Cloud 30
ドキュメントをどのように学 習させるべきか ? Vertex AI Search で RAG を行う...? Google Cloud 31
RAG の課題 ● 包括的な知識を必要とする質問に対して精度が出ない ● データ更新にある程度遅延があり、試行錯誤がしにくい Google Cloud 32
偶然気になる情報が ... Many-Shots In-Context Learning (ICL) という、 プロンプトに全部叩きこむ手 法を Gemini で使うと 高い性能が出るらしい ...?? Google Cloud 33
Many-Shots In-Context Learning (ICL) とは? ● Google DeepMind の同名の論文で提唱された手法 ● Few-Shots のように、プロンプトに入力として与えた例から、事前学習なしでタスクを学習させる ● Few-Shots の入力データ量をスケールさせることで、性能が大幅に上がる、という趣旨 ● Gemini 1.5 は Flash で 1Mトークン、Pro で 2Mトークンと非常に大きなコンテキストウィンドウを持つ ● Gemini 1.5 は Many-Shots In-Content Learning を行うのに、非常に向いている LLM といえる Google Cloud 34
Gemini のロングコンテ キスト性能 を活かし、 全てのドキュメント を プロンプトとして送信 することに Google Cloud 35
全てのドキュメント を プロンプトとして送る # ドキュメント ## 言語仕様 .md 言語仕様 ドキュメント ## コンバータ .md ● プロンプトを前半のドキュメント 、後半の質問文の 2 つのブロックに分ける ● ドキュメントのブロックにドキュメントの全文を直接埋め込む ● 最後に質問文のブロックにユーザからの質問文を埋め込む コンバータ ドキュメント ## コンパイラ .md ## ランタイム API.md … # 以下は質問文 Muscle で実際にスキーマ記述 を行い、データ入力、コンバー ト、ランタイム読み込みまでを行 う迄の手順を教えて下さい。 Google Cloud 36
RAG と Many-Shots ICL の 回答品質を比較 Google Cloud 37
与える質問 : “簡単なカードゲームのマ スタデータの構造を Muscle の DSL として 出力して ” Google Cloud 38
Gemini 1.5 Flash での結果 Google Cloud 39
RAG の例 Many-Shots ICL の例 40
RAG
message Card {
storage.use: true
}
required uint32 id = 1; primary_key: true
required string name = 2;
required uint32 cost = 3;
required uint32 attack = 4;
required uint32 defense = 5;
message Skill {
storage.use: true
}
required uint32 id = 1; primary_key: true;
required string name = 2;
required string description = 3;
message CardSkill {
storage.use: true
required uint32 card_id = 1; primary_key: true
required uint32 skill_id = 2; primary_key: true
}
Many-Shots ICL
message CardMaster {
option (muscle.message) = {
table: true,
master_memory: { use: true },
oyakata: { use: true }
};
int64 id = 1 [(muscle.field) = { primary_key: true }];
string name = 2;
string description = 3;
CardType card_type = 4;
int32 attack = 5;
int32 defense = 6;
repeated string abilities = 7;
string imageUrl = 8;
}
message DeckMaster {
option (muscle.message) = {
table: true,
master_memory: { use: true },
oyakata: { use: true }
};
int64 id = 1 [(muscle.field) = { primary_key: true }];
string name = 2;
repeated int64 cardIds = 3; // CardMaster.idへの参照
}
enum CardType {
CARD_TYPE_UNKNOWN = 0;
CARD_TYPE_ATTACK = 1;
CARD_TYPE_DEFENSE = 2;
CARD_TYPE_SPECIAL = 3;
}
41
RAG ドキュメントの全体を 体系的に捉えておらず 、 Muscle として誤った 構文の内容 を生成している。 Many-Shots ICL ドキュメントの全体を 体系的に捉えて 、 Muscle として正しい構文の 内容を生成している。 一方で、 基本機能を使いこなせて いない部分も見られる 。 42
Gemini 1.5 Pro での結果 Flash からどう変化する ? Google Cloud 43
RAG
message Card {
primary_key int id;
required string name = 1;
required int cost = 2;
required int attack = 3;
required int defense = 4;
}
message Deck {
primary_key int id;
required string name = 1;
repeated int card_ids = 2;
}
message Player {
primary_key int id;
required string name = 1;
optional int selected_deck_id = 2;
}
Many-Shots ICL
// バージョン定義
option (muscle.file) = { versions: [
{ value: 10000, name: "1.0.0", display_name: "初期リリース" },
{ value: 10100, name: "1.1.0", display_name: "バランス調整アップデート" }
]};
// カードの種別を定義するEnum
enum CardType {
option (muscle.enum) = {
master_memory:{use:true}, oyakata:{use:true},
takasho:{use:true}, required_version:10000
};
CardType_Default = 0;
CardType_Attack = 1;
//略
}
// カードのレアリティを定義するEnum
enum CardRarity {
option (muscle.enum) = { /* 筆者略 */ };
CardRarity_Default = 0;
CardRarity_Common = 1;
//略
}
// カードマスタ
message CardMaster {
option (muscle.message) = {
table: true, master_memory: { use: true }
takasho: { use: true }, oyakata: { row_versioning: true }
};
int64 Id = 1 [(muscle.field) = { primary_key: true }];
string Name = 2;
CardType Type = 3;
CardRarity Rarity = 4;
/* 筆者略 */
}
// デッキマスタ
message DeckMaster {
option (muscle.message) = { /* 略 */ }; /* 筆者略(Id, Name等) */
repeated CardMaster CardIds = 3; // デッキに含まれるカードのIDリスト
}
// プレイヤーマスタ
message PlayerMaster {
option (muscle.message) = { /* 略 */ }; /* 筆者略(Id, Name等) */
repeated CardMaster CardIds = 4;// プレイヤーが所持しているカードの
IDリスト
repeated DeckMaster DeckIds = 5;// プレイヤーが所持しているデッキの
IDリスト
}
/* 略: Card,Deckを持つPlayerMasterと、Play,Deckを持つBattleMaster も出力された*/
44
RAG ドキュメントの全体を 体系的に捉えておらず、 構文的に誤っているまま。 マスタ構造のディテールも 粗いまま。 殆ど変化がない。 Many-Shots ICL ドキュメントの全体を 体系的に捉えて、 正しい構文であるまま、 複数機能を駆使した 複雑な内容 を 生成するようになった。 マスタ構造のディテールも 細かくなっており、 回答品質が 目に見えて向上 している 45
ICL を用いることで、 ドキュメントに記述された 事実を答えるだけでなく、 内容の体系的な理解が必要な タスクを処理する能力 を 高度なレベルで獲得 した Google Cloud 46
ICL はモデルの力を生かしやすい。 RAG の品質に影響されず 、 モデルの性能改善が回答の品質改 善に大きく影響する ため、 より良いモデルを使うことで、 より難しい質問に答えられる ようになる。 Google Cloud 47
“Rinchan”は Gemini だからこそ成立した ● 先ほど例として出した Muscle の既存のドキュメントだけでも、合計で 100K トークン前後 ● 同時に読ませたい、関連する別システムのドキュメントもそれぞれ 50K~80K トークン前後 ● 多くの LLM の限界値である 128K を容易に超えうるが、 1M / 2M トークンまで Gemini 1.5 なら扱える ● 複数のライブラリに関連する質問にも、それぞれのドキュメントを同時に与えるだけで答えられる ● つまり、コンテキストウィンドウの制約上、 ”Rinchan” は Gemini 1.5 以外では実現できない Google Cloud 48
In-Context Learning は運用が非常に容易 ● Gemini はプロンプト内で Cloud Storage 上のオブジェクトの URI を指定してファイルを読みこめる ● ドキュメントを Cloud Storage バケット上に管理しておき、指定ディレクトリ以下のものをプロンプトに入力 ● 極めてシンプルなフローで、即座に学習対象のドキュメントを更新できる ● 非常に早いイテレーションで試行錯誤が可能 Google Cloud 49
“Rinchan” の 構成は 極めて単純 ● SlackApp を含めて Google Cloud 上に構築 ● ドキュメントは全て Cloud Storage のバケットに格納 ● 特定のキーワードが質問文に含んでいるかをみて、 特定ディレクトリ以下を全てプロンプトに含める ● スレッド毎のプロンプト履歴を別のバケットに格納し、 スレッド単位で対話的に会話できるように Google Cloud 50
In-Context Learning によるデメリット ● 入力トークン数が多いため、RAG に比べて料金的なコストはかかる(以下は4文字1トークンの仮定での計算) ○ Gemini 1.5 Flash は 1Mトークンで $0.1404 という価格になった為、 社内用のAIエージェントでの利用頻度では殆ど問題にならないほど安く運用が可能。 ○ Gemini 1.5 Pro も 10/7 から 1Mトークンで $2.34 という価格まで下がった為、 積極的に使っていける。 ”Rinchan” では Gemini 1.5 Pro をデフォルトで使う形で運用中 ● 入力トークン数が多いため、回答の生成にある程度時間がかかる ○ 利用頻度次第では Context Cache を活用することで、コスト圧縮や回答の高速化を狙える ○ ドキュメント部分までのプロンプトの Cache を作り、異なる質問の間で共有することが可能 ○ Context Cache は最小 32769トークンという制限がネックだが、 ICL では確実に超える為相性が良い Google Cloud 51
04 ドキュメンテーションの 価値を高める Google Cloud 52
In-Context Learning のための ドキュメンテーション ● うまく答えを返せなかった場合も、既存のドキュメントに足りない事実を追記することで、 答えを返せるようになることが多い。 ● サンプルコードなどを添えて例示をしっかり行っているライブラリほど高い精度がでる傾向もある ● ドキュメントに記述された本質的な内容が、直接的に回答の精度に大きく影響している ● RAG などと異なり、チャンク化などを意識した、 AI のためのドキュメンテーションは必要ない ● 人間が考えるべきことが少ないドキュメントは、AI にとっても考えるべきことが少なくすむのでは Google Cloud 53
RAG で必要なチャンク単 位の考慮は不要 人に分かりやすい記述を すれば、 AI にも伝わる Google Cloud 54
書かれていない事実 は AI も認識出来ない。 不足した事実を記述 して 認識を改善する。 Google Cloud 55
AI にとって価値のある ドキュメント ではなく、 本質的な価値のある ドキュメント を書くべき Google Cloud 56
“Rinchan” によるドキュメントの改善 ● “Rinchan” が正しい回答を返せない時 は、ドキュメント改善の機会 でもある ○ ”Rinchan” が理解できないことは、人にも理解が難しい ○ “Rinchan” が使われるほど、ドキュメント改善の機会も増える ● “Rinchan” 自体にドキュメントの改善のための回答をさせる ○ ドキュメントの不整合や曖昧な点をレビュー させて、それを参考に人間がドキュメントを改善 する ○ 新機能の概要を伝えることで、ドキュメントの草稿を作らせる Google Cloud 57
“Rinchan” による ドキュメンテーションの好循環 ● ドキュメントを改善することで、ドキュメントの価値が高まると同時に “Rinchan” の性能は目に見えて向上する ● ”Rinchan” の性能の向上が、 ”Rinchan” を使ったドキュメントの改善につながる ● このサイクルが、ドキュメンテーション自体の価値を大きく向上させる ドキュメントの 改善 Google Cloud ドキュメントの 価値の向上 “Rinchan” の 性能向上 58
01 今後の展望 Google Cloud 59
現状の “Rinchan” の取り組みの 強化 ● 実用物として提供しながらも、検証 / 改善を続けている状態 ● 主に短期的なマルチターン会話を高速化するため、Context Cache によるレスポンスタイムの短縮も検討 ● ドキュメント更新フローの自動化など、パイプライン側でやるべきことも残っている Google Cloud 60
特定のゲーム専用 の “Rinchan” の提供 ● ゲームごとの仕様書,マスタデータ,マスタデータスキーマなども入力として与えた版を、開発チームに提供する ● 単なる社内ライブラリの扱い方だけでなく、ゲーム自体の開発補助に “Rinchan” の考え方を応用する ● 直接的な成果物を伴わないような、細かな仕事を柔軟にサポートするのが目的 ● ゲーム固有の情報は膨大なため、主に情報密度の薄いものを対象に RAG や Function Calling を併用を考える ● RAG には Vertex AI Search の Answer API , Third-Party Data Source など、新しい強力な手段を検討していく ● ゲームタイトルによっては社外を含めステークホルダーが多くなる。入出力範囲や活用方法は個別に取り決める Google Cloud 61
Thank you Google Cloud