Upgrade to Pro — share decks privately, control downloads, hide ads and more …

コードレビュー支援ツール開発から学ぶ:LLMを用いた業務システムの実践的な運用設計と誤出力対策

 コードレビュー支援ツール開発から学ぶ:LLMを用いた業務システムの実践的な運用設計と誤出力対策

2026/07/24 CEDEC2026

Avatar for Cygames, Inc.

Cygames, Inc. PRO

August 03, 2026

More Decks by Cygames, Inc.

Other Decks in Technology

Transcript

  1. 登壇者紹介 インフラ / マネージャー インフラ / サブマネージャー インフラ 佐藤 太志

    山崎 公之 恩田 大輝 SIerを経て、2011年に株式会社 Cygamesへ合流 2016年よりマネージャー 2024年よりエンジニア2部副部長兼任 複数のゲーム会社で開発およびサーバ /ネットワークインフラ業務を経て、 2012年に株式会社Cygamesへ合流 開発支援チームのリーダーとしてイン フラ作業の自動化や効率化を推進 ゲーム開発会社のバックエンドエンジ ニアを経て、2021年に株式会社 Cygamesへ合流 開発支援チームに所属し、コードレ ビュー支援ツールの開発・運用に従事 4 /82
  2. 「Lyra」の概要 GitHubのプルリクエストをAIがレビュー レビュー結果をコメントでフィードバック 2つの主要機能 開発者 ❶プルリクエスト作成 GitHub ❷レビュー ❺レビュー結果を コマンド検知

    コメント ❸レビュー項目を インプット LLM ❹アウトプットを取得 ◆ コードレビュー ◆ プルリクエストの要約・説明 導入の容易さ ◆ GitHubアプリとして提供 ※GitHub Enterprise Server 対応 Lyra 13 /82
  3. コードレビュー機能の概要 依頼 Pull Requestに /review or /r とコメント 解析 Lyraが差分・周辺コード・設定を

    取得し、レビューを実行 投稿 良い点・改善点・修正案を レビューコメントとして投稿 プルリクエスト上の自然な操作だけで、 コードレビュー支援を開発フローに組み込む 14 /82
  4. プルリクエストの要約・説明機能の概要 依頼 Pull Requestに /summarize or /s とコメント 解析 Lyraが差分・周辺コード・設定を

    取得し、PRの要約と説明を自動作成 投稿 概要・詳細・変更一覧を descriptionとして投稿 プルリクエストの概要や変更箇所を自動作成、 レビュー前に変更内容をすばやく把握できます 16 /82
  5. インタラクティブ機能の紹介 修正案をその場で確認 ❶ Suggested changeで具体的な変更を提示 修正案を提示 PR上で追加確認 コメント返信だけで会話を継続 ❷ 開発者が返信

    対応後の再確認 修正内容への補足 再レビューを支援 ❸ AIが再確認 プルリクエスト上の自然な操作だけで、 コードレビュー支援を開発フローに組み込む 20 /82
  6. 表記が揺れる:分類・パース・集計が不安定になる 分類できない パースが壊れる 集計できない 表記が毎回違うと、 品質・安全性などの分類 が安定しない Markdown頼みだと、 必要な項目を取り出せ ないことがある

    形式がそろわないと、 指摘数や傾向を数えら れない 例 「改善点」/「Issues」/「指摘」 例 例 必須見出しが見つからない レビュー品質の変化を追えない 出力を「文章」として期待するのではなく、 「データ構造」として固定する必要がある 28 /82
  7. データとして処理できない:自由記述の限界 人は内容を理解できるが、検索・集計に必要な 情報をシステムが安定して取り出せない 自由記述のレビュー 「src/service/user.ts で、取得した user をそのまま参照しているように見 えます。user が

    null の場合に後続処理 で例外になる可能性があるため…」 何が問題か、どこが対象か、 重要度が文章中に埋もれる フォーマットされたレビュー 問題:null チェックが不足 対象:src/service/user.ts:42 重要度:Important 推奨:早期 return を追加 必要な情報を項目として取り出せる 31 /82
  8. データとして処理できない:管理できない情報 レビュー結果から対象箇所・優先度・状態を項目として取得する 指摘箇所が 特定できない 優先度が 分からない 対応状態を 管理できない 必要な情報 ファイル名・行番号

    必要な情報 必要な情報 重要度 必要な情報 必要な情報 指摘ID・状態 必要な情報 使い道 使い道: 表示する 使い道 使い道: Critical / Important / Optional に 分類する 使い道 使い道: 除外・再通知・改善 分析に使う GitHubの対象行に 必要な情報を項目として取り出せる形にし 表示・集計・改善につなげる 32 /82
  9. レビュー結果を構造化JSONで受け取る LLMの構造化出力(JSON)をテンプレートに適用し、GitHubコメントを生成 LLMの構造化出力(JSON) { “file”:”src/service/handler.go”, “line”: 128, “title”: “ユーザー入力の検証漏れ”, “severity”:”High”,

    “problem”: “入力値の検証が不足しており、 予期しないエラーが発生する可能性がある”, “recommendation”: “入力値の検証を 追加し、エラーハンドリングを改善する” } テンプレートに 適用 GitHubインラインコメント (テンプレート適用後の表示例) L Lyra Comment on lines 128 to 128 タイトル ユーザー入力の検証漏れ 重要度 High 問題 入力値の検証が不足しており、予期し ないエラーが発生する可能性がある 推奨対応 入力値の検証を追加し、エラーハンド リングを改善する 内部表現はJSON、表示はテンプレートで制御する 34 /82
  10. LLMとLyra側の処理の役割分担 Lyra側(GitHub App)の処理 保存した データ JSON LLM ❶ AWS JSONを返す

    S3に保存 Mark down API ❷ ❸ テンプレート 適用 GitHubへ 投稿 GitHub PRにコメント LLMに任せるのは、JSONを返すところまで GitHubに出す前にLyra側で保存・整形・投稿する 35 /82
  11. 指摘データ蓄積・活用する仕組み 表示に使うJSON 裏側で持つフィールド file line title severity problem recommendation AWS

    S3 短期 採用 / 却下 / フィードバックを追跡 Finding_id status feedback posted_at … 指摘データを運用改善に活用する仕組み 中期 プロジェクト別・ 時系列で集計・分析 長期 蓄積データでレビュー 内容をチューニング 39 /82
  12. 例:存在しない関数を前提にした指摘 具体的な関数名まで書かれているため、文章だけでは正しそうに見える LLMが出した指摘 実際のコード確認 メールアドレスをそのまま保存す ると、前後の空白や大文字小文字 の違いで重複判定が揺れる可能性 があります。 既存の `normalizeEmail()`

    を通してから保存してください。 このリポジトリに `normalizeEmail()`は存在し ない。メール正規化の共通関数 も定義されていない。 一見もっとらしく見える指摘 存在しない関数を前提にしている もっともらしい関数名まで書かれているため、 実装と照合しないと気づけない 44 /82
  13. 試作方式で見えた成果と課題 良かった点 実運用上の課題 ◆ 誤指摘を減らせた ◆ 根拠の薄い指摘を落とせた ◆ 判断の根拠を残せた ◆

    処理が長くなる ◆ 実装が複雑になる ◆ 新しいモデルを取り込みにくい 業務システムとして使うには、精度だけでなく、 処理時間・実装の見通し・モデル更新への追従性も必要 方向転換へ 49 /82
  14. 直列の深掘りから、並列エージェントのディベートへ 従来:直列の深堀り 新方針:並列エージェントのディベート 初期版 ディベート プロンプト1回 出力 Agent A Agent

    B Agent C Agent D 試作版 プラン 調査 検証 投稿判定 ◆ 手順は人が決める ◆ 決まった順番でLLMを呼ぶ ◆ 手順でLLMを縛る使い方 処理・実装が重く、差し替えにくい ◆ 4つのAIエージェントが並列に議論 ◆ ディベートで合意した指摘だけを採用 エージェント単位で差し替え・性能 向上を取り込める この設計方針が「マルチエージェント設計」 51 /82
  15. 最終アーキテクチャ 入力 並列レビュー + 4つのエージェントでディベート GitHub PR 差分 (diff) 本文

    (PR本文) 設定 (ルール/プロ ンプト等) Security / Claude Quality / Claude 出力制御 採用して公開 合意指摘を表示 GitHub /インラインコメント 4つのエージェントでディベート 相互検証・合意形成 不採用も 折りたたみで投稿 反証・不確実・ノイズ Security / Codex Quality / Codex 折りたたみで投稿 必要に応じて展開 複数視点の合意で、表示する指摘を制御する 52 /82
  16. 出力制御 前章で紹介したインライン・折りたたみ表示を使って、 合意結果に応じて採用・不採用を制御 合意結果 重要度ラベル 表示場所 採用(優先度高) Critical/ Important インラインコメント・サマリに件数表示

    採用(低) Optional サマリー内に折りたたみ 不採用の指摘 サマリー内に折りたたみ 不採用 利用者に届ける情報量を制御し、 重要な指摘に集中できる状態を作る 53 /82
  17. 結果 2:候補から信頼できる指摘だけを抽出 種別 件数 生成指摘数 8,652件 不採用指摘数 5,311件 採用指摘数 (約61%)

    3,341件 (約39%) 約6割を不採用 反証あり/不確実/ノイズ 約4割を利用者へ 信頼できる指摘だけを届ける 「LLMが出したから出す」ではなく、 合意できたものだけを届ける 55 /82
  18. 結果 3:ベンチマークでも有効性を確認 SWE-PRBench eval_100 で、Lyraは論文で報告されている 各LLM単体のスコアを上回る平均スコア・検出率と、低い誤指摘率を確認 SWE-PRBench paper v1 Table

    8 / arXiv:2603.26130 対象 平均スコア (Mean) 検出率 (DRA) 誤指摘率 (FPRavg) ※低いほど良い 1 Lyra 0.475 0.560 0.119 2 Claude Haiku 4.5 0.153 0.306 0.346 3 Claude Sonnet 4.6 0.152 0.297 0.227 4 DeepSeek V3 0.150 0.312 0.315 5 GPT-4o 0.113 0.220 0.193 平均スコア 検出率 誤指摘率 (Mean) (DRA) (FPRavg) ※低いほど良い +210% +79% -38% 論文内 top mean との比較で向上 論文内最大DRA との比較で向上 論文内最良FPRavg との比較で低減 比較条件:値は論文内で報告のあった各LLMの数値(Table8)。Lyraはマルチエージェント合意型。モデル世代・呼び出し方式が異なる点に留意。 調査・合意・出力制御により、ベンチマーク上でも品質向上を確認 56 /82
  19. 集計に必要なデータを収集 GitHub (PRイベント発生) Lyra Webhook (HTTPS) イベントデータから 必要なデータを抽出 イベントデータ ログ

    コメント本文 /review PR番号 投稿者 コメント本文 その他 メタデータ イベント データ PR番号 投稿者 イベントをキャッチしてデータを抽出し、ログに出力する 65 /82
  20. 集計しやすい形式でログに出力 抽出したパラメータを集計しやすいJSON形式でログ出力 GitHubから イベントデータを受信 { “message”: “An error has occurred”,

    “context” : { “deliveryId”: “XXXX”, “organization”: “PJ_NAME”, “repository”: “REPOSITORY_NAME”, ... } 必要な情報を 抽出 JSONログとして出力 } JSON形式にすることで、BIツール、監視ツール等で応用しやすい形に 66 /82
  21. これだけだと不十分 複数のリクエストが同じ時間帯に出力された場合、追跡が困難になる time message 10:00:01 イベント受信 リクエストA 10:00:02 イベント受信 10:00:04

    処理開始 10:00:06 処理完了 リクエストB どのリクエストの ログか不明 (追跡が困難) 10:00:07 処理開始 10:00:08 処理完了 10:00:09 イベント受信 10:00:11 処理開始 リクエストC 10:00:12 処理完了 67 /82
  22. 追えるIDみたいなものがあれば… トレースIDを付与することでイベント処理をID単位で追跡可能に リクエストA リクエストB リクエストC TraceID time message a1b2c3 10:00:01

    イベント受信 b4d5e6 10:00:02 イベント受信 a1b2c3 10:00:04 処理開始 a1b2c3 10:00:06 処理完了 b4d5e6 10:00:07 処理開始 g7h8i9 10:00:08 処理完了 g7h8i9 10:00:09 イベント受信 g7h8i9 10:00:11 処理開始 b4d5e6 10:00:12 処理完了 どのリクエストの ログかIDで 判別可能に (追跡が容易) 68 /82
  23. TraceIDにGitHubのDeliveryIDを採用 1. ユニークな ID を選定 ◼ Trace ID として GitHub

    から届く一意な ID( Delivery ID ) を利用 2. ユニークな ID をログイベントに紐づける ◼ すべてのログイベントに Delivery ID を残すことで、 処理の過程を一連の流れとしてログから追えるようになる GitHub WebhookEvent Lyra Delivery ID: a1b2c3 Delivery ID: a1b2c3 ユニークな ID を決めて、すべてのログイベントに付与する 69 /82
  24. トレーサビリティの確保 Lyra内のレビュー処理をDelivery IDでつなげる ログ出力 Delivery ID イベント単位で ユニークな値 受付処理 {

    delivery_id: a1b2c3, level: info, phase: 受付 } バリデーション処理 { delivery_id: a1b2c3, level: info, phase: バリデーション } レビュー処理 { delivery_id: a1b2c3, level: info, phase: レビュー } 出力処理 { delivery_id: a1b2c3, level: info, phase: 出力 } 同じ ID を持たせることで、一連の処理を 1件のリクエストとして追跡しやすい形に 70 /82