- AWS Builder Center›
- builders.flash
kintone における生成 AI 機能の安全な運用 ~ 分散トレーシングによる運用課題の解決
2025-11-04 | 齋藤 耕平 (サイボウズ株式会社)
はじめに
はじめまして、サイボウズ株式会社の kintone 開発チーム の齋藤です。
kintone の生成 AI 機能のバックエンド開発を担当しています。
本記事では、大規模なマルチテナントの SaaS である kintone に生成 AI 機能を導入する際の課題と、それを解決するためのアーキテクチャについて解説します。
生成 AI 特有の不確実性によって発生する問題やテナント毎のトークン消費量など、AWS CloudWatch Application Signals を活用して可観測性を強化した事例を紹介します。
builders.flash メールメンバー登録
builders.flash メールメンバー登録で、毎月の最新アップデート情報とともに、AWS を無料でお試しいただけるクレジットコードを受け取ることができます。
kintone における生成 AI 機能の概要
kintone とは
kintone は、サイボウズが提供する業務アプリケーション構築プラットフォームです。プログラミング知識がなくても、Web ブラウザ上でデータベースやワークフローを組み合わせた業務アプリケーションを簡単に作成できることが特徴です。
現在、 38,000 社以上の企業で利用されており、このような大規模なマルチテナント SaaS として、安定した運用と継続的な機能改善が求められています。
kintone における生成 AI 機能
現在、 kintone では「検索 AI」「アプリ作成 AI」「プロセス管理設定 AI」という 3 つの生成 AI 機能を提供しています。
「検索 AI」 は、 kintone アプリに蓄積されたデータを活用した RAG (Retrieval-Augmented Generation) 機能です。「アプリ作成 AI」は、自然言語での要求から kintone アプリの設計を自動生成する機能です。「プロセス管理設定 AI」は、実現したい業務プロセスを自然言語で要求すると、AI が適切なワークフローを提案し、ワンクリックで設定できます。
これらの kintone の生成 AI の機能は Amazon Bedrock を基盤として構築されており、企業の機密データを安全に処理しながら、高品質な生成 AI 体験を提供しています。
AI 機能のアーキテクチャ
kintone から Amazon Bedrock の LLM の呼び出し、その生成結果を取得する仕組みは図のようになっております。
LLM 呼び出しと生成結果取得の流れ
LLM の呼び出し
- クライアントから kintone に対してリクエストを行うとLambda 関数 AIServiceFunction に LLM の呼び出しをリクエスト
- AIServiceFunction は別の Lambda 関数 AIServiceAsyncEventFunction に LLM 呼び出しを行う非同期処理リクエスト
- AIServiceAsyncEventFunction が LLM (Anthropic Claude 3.5 Sonnet など) に対して Invoke を行い生成結果を受け取り、ElastiCache (Valkey) に順次書き込み
LLM 生成結果の取得
- 生成結果の取得は生成リクエスト時にレスポンスされたIDを使いリクエスト
- 生成結果は Valkey に順次書き込まれるため、ポーリングをして最新の生成結果を取得しクライアント(ブラウザ)に表示
NOTE
一般的な生成 AI 機能では、LLM からの応答をリアルタイムで表示する Streaming Response 方式が採用されることが多いですが、kintone では大規模 SaaS でのスレッド制約を考慮し、ポーリング方式を選択しました。これにより接続時間の最小化、処理の分離、スケーラビリティの向上を実現しています。
大規模 SaaS における生成 AI 運用の課題
Amazon Bedrock を活用した生成AI機能を本格運用する中で、従来の Web アプリケーションとは異なる特有の課題が浮き彫りになりました。
主要な運用課題
- 生成 AI 特有の不確実性 : 同じプロンプトでも毎回異なる結果が生成される可能性があり、「昨日は正常に動作したのに今日はエラーになる」といった問い合わせの調査が困難
- エラーの根本原因特定の困難さ : プロンプト生成、RAG 処理、LLM 呼び出し、後処理など複数のステップを経る複雑な処理フローで、どの段階で問題が発生したのか従来のログだけでは特定が困難
- テナント毎のトークン消費量の可視化 : 一部のテナントで過剰に利用してしまい、他のテナントに影響を与えないよう、適切な監視とケアが必要。また、コスト管理の観点からもテナント毎の消費量を可視化することが重要
- 非同期処理による複雑性: 複数の AWS Lambda 関数と AWS サービスを経由する処理の全体像を把握することが困難
- 複雑なログ分析による運用負荷の増大 : 複数の Lambda 関数間でのログを横断的に分析する必要があり、調査の難易度が大幅に上昇
これらの課題を解決するため、AWS CloudWatch Application Signals を活用した分散トレーシングによる可観測性の向上に取り組みました。
AWS CloudWatch Application Signals の活用
分散トレーシングの基本概念
分散トレーシングは、マイクロサービスアーキテクチャや分散システムにおいて、一つのリクエストが複数のサービスやコンポーネントを横断する際の処理の流れを追跡・可視化する技術です。
主要な構成要素:
- トレース (Trace) : 一つのリクエストに対する処理の全体を表す単位
- スパン (Span) : トレース内の個別の処理単位。開始時刻、終了時刻、処理名、属性情報などを持つ
OpenTelemetry の実装
基本的な計装
FastAPI アプリケーションに対して以下のライブラリをインストールし、数行のコードを埋め込むことで実現:
- opentelemetry-instrumentation-fastapi : HTTP リクエスト/レスポンスを自動的にトレース
- opentelemetry-instrumentation-botocore : AWS SDK の呼び出しに対して自動的にスパンコンテキストを埋め込み
- opentelemetry-instrumentation-logging : Python の標準ログとトレースを関連付け
OpenTelemetry Collector の最適化
当初は AWS Distro for OpenTelemetry Collector (ADOT Collector) を採用していましたが、200ms 以上のレイテンシーオーバーヘッドが発生しました。現在は、OpenTelemetry Collector AWS Lambda Extension Layer の decouple プロセッサを活用することで、完全に非同期でスパンの送信を行い、約 150ms の改善を実現しています。
詳しくは Observing Lambdas using the OpenTelemetry Collector Extension Layer を参照してください。
スパンリンクによる異なるリクエスト間の関連付け
AI 機能のアーキテクチャでは、LLM の呼び出しと生成結果の取得が異なるリクエストになっているため、通常の方法では両者の関連性を持たせることができません。
この課題を解決するため、Valkey を介したスパンコンテキストの伝搬とスパンリンクを活用しました。
- LLM の生成結果を Valkey に書き込む際に、スパンコンテキストを含める
- 生成結果取得時に、Valkey から取得したスパンコンテキストを現在のスパンにリンク
スパンコンテキストの保存と追加
# スパンコンテキストの保存
def init_carrier():
carrier: dict = {}
TraceContextTextMapPropagator().inject(carrier)
# carrier を Valkey に書き込むオブジェクトのフィールドに設定する (省略)
# スパンリンクの追加
# Valkey から取り出したオブジェクトから carrier フィールドを読み込む部分は省略
def add_span_link_from_carrier(carrier):
propagator = TraceContextTextMapPropagator()
ctx = propagator.extract(carrier)
referrer_span_context = trace.get_current_span(ctx).get_span_context()
trace.get_current_span().add_link(referrer_span_context)
カスタム属性の効果的な活用
スパンには以下のような属性を付与し、詳細な分析を可能にしています。
|
属性名
|
属性値例
|
説明
|
|---|---|---|
|
kintone.tenant_id
|
z9999999 |
kintone のテナント識別子 |
|
kintone.user_id
|
12345 |
リクエストを実行したユーザーの ID |
|
gen_ai.usage.input_tokens
|
3527 |
LLM への入力トークン数 |
|
gen_ai.usage.output_tokens
|
251 |
LLM からの出力トークン数 |
運用改善への活用事例
OpenTelemetry と CloudWatch Application Signals の導入により、前述の 5 つの主要課題を以下のように解決しました:
1. 生成 AI 特有の不確実性への対応
テナント識別子でフィルタリングし、成功時と失敗時のトレースを比較。スタックトレース情報により即座に原因を特定。
2. エラーの根本原因特定の困難さの解消
トレースマップとスパンタイムラインにより、処理フローとエラー箇所を視覚的に確認。
3. テナント毎のトークン消費量の可視化
入出力トークン数とテナント識別子などの属性をスパンに埋め込み、CloudWatch カスタムダッシュボードで可視化。
4. 非同期処理による複雑性の解決
トレースマップによる処理フローの視覚化と、スパンリンクによる関連付け。
5. 複雑なログ分析による運用負荷の軽減
直感的なトランザクション検索により、複雑なログクエリが不要に。 特に重要な点は、複雑なログクエリの習得や属人的な調査スキルに依存することなく、直感的なUIと豊富な属性情報により、運用チーム全体の調査能力が底上げされたことです。
導入の注意点
性能への影響
OpenTelemetry の計装により、アプリケーションのレスポンス時間に若干のオーバーヘッドが発生します。適切な Collector の選択により、この影響を最小化することが重要です。
計装ライブラリによる振る舞いの変化
OpenTelemetry の計装ライブラリの導入により、既存のアプリケーションの動作に予期しない変更が生じる可能性があります。十分なテストを実施してから本番環境に適用することを推奨します。
まとめと今後の展望
本記事では、大規模 SaaS kintone における生成 AI 機能の運用課題を、AWS CloudWatch Application Signals による分散トレーシングで解決した事例を紹介しました。従来のログベースの監視では対応困難だった生成 AI 特有の課題に対して、OpenTelemetry による計装とカスタム属性の効果的な活用により包括的な解決を実現しました。
今後は、SLO 機能を活用した品質管理の強化、Valkey GLIDE 2.0 による Amazon ElastiCache アクセスの可視化、ユーザーフィードバック機能との連携などを検討しています。
生成 AI 技術の急速な進歩に伴い、運用における可観測性の重要性はますます高まっています。本記事で紹介した手法が、同様の課題に直面する開発・運用チームの参考となり、より安定した生成 AI サービスの提供に貢献できれば幸いです。
筆者プロフィール
サイボウズ株式会社
バックエンドエンジニア
AWS を活用して kintone の価値向上に日々取り組んでいます。