0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

(Neptuneとか高いねん)AWSブログのB-pillar DFMEA構成を軽量化してコストカットしても動きます

0
Posted at

はじめに

2026年9月27日、AWS for Industries ブログに「Building AI-augmented B-pillar DFMEA on AWS: Architecture, multi-agent orchestration, and implementation」という記事が公開されました。

自動車のBピラー(前席と後席の間の柱)を題材に、DFMEA(設計段階で故障モードとその影響を洗い出すレビュー)をマルチエージェントで支援する構成を解説した記事です。
シリーズ前編では、手作業のB-pillar DFMEAは潜在故障モードの40〜60%を見落とすと主張していました。
材料・工程・故障メカニズム・影響の因果連鎖をオントロジーとして持たせれば、AIは過去文書のパターン照合ではなく推論ができる、という立場です。

構成を読んで最初に気になったのはコストでした。この記事では次の3点を扱います。

NeptuneとOpenSearch Serverlessが高い

  • 元記事の構成をそのまま作ると、何もしなくてもいくらかかるか
  • どこを残し、どこを削れば個人でも試せる規模になるか
  • 軽量化しても、オントロジーで検証するという核の部分は再現できるか

実装はGitHubに公開しています。

元記事の構成

元記事は6つのレイヤーで構成されています。

  • フロントエンドと認証: Amazon S3+Amazon CloudFront(OAC)、Amazon Cognito、Amazon API Gateway REST、AWS WAF、AWS Lambda から AWS Step Functions を起動
  • AWS Step Functions: 取り込み→抽出→MLによる事前スクリーニング(ランダムフォレスト、Isolation Forest)→専門エージェント4つ→分析エージェントがPDFを出力。HITL(人による承認)ゲートが4つ
  • 非同期取り込み: 署名付きURLでS3へアップロードし、Amazon EventBridge 経由で Amazon Textract がOCR
  • WebSocket: API Gateway WebSocket で進捗を通知し、接続IDは Amazon DynamoDB に保存
  • Amazon Bedrock AgentCore: 専門エージェントをそれぞれ AgentCore Runtime で動かし、MCP経由で DynamoDB・Amazon Bedrock Knowledge Bases・Neptune・S3 にアクセス
  • データ: AWS KMS、DynamoDB、S3、Amazon OpenSearch Serverless(Knowledge Bases のベクトルストア)、Amazon Neptune

オントロジーは Amazon Neptune に置き、SPARQLで引きます。更新経路は3つあります。

  • JSON-LDをN-Quadsに変換して一括ロード
  • Amazon A2I を使った人手承認のキュレーション
  • AIAG・VDA・ISOの四半期ごとの取り込み

レビュー開始時にオントロジーのバージョンを固定する(version-pinning)仕組みも入っています。

image.png
© 2026, Amazon Web Services, Inc. or its affiliates. All rights reserved.

元記事の中心は「オントロジースレッド」と呼ばれる考え方でしょう。
エージェントが出した故障モードは有効なIRI(オントロジー上の識別子)に解決できなければならず、因果連鎖は Neptune 上でたどれなければならず、矛盾が出たらオントロジーを優先して解決する、というルールです。

なお、元記事には記述の食い違いがいくつかあります。

  • 本文は「専門4+分析1」のエージェント構成、結論は「チャット、オーケストレーター、GAP検出3つの5エージェント」
  • 図の説明は「SPARQLクエリ7段階」、表はS1〜S6の6段階
  • 結論に編集用の「[JD1]」が残っている
  • GitHubリポジトリがあると書かれているものの、本文にURLがない

そのまま作ると常時課金が重い

元記事の構成には、使っていない時間も課金されるサービスが含まれています。
us-east-1 の料金を2026年9月28日に AWS Price List API と料金ページで確認しました。

サービス 最小構成 月額の目安(730時間)
Amazon Neptune Database db.t4g.medium 1台($0.093/時間) 約$68(ストレージ・I/O別)
Amazon OpenSearch Serverless(クラシック) 最低1 OCU(インデックス0.5+検索0.5、冗長化なし) 約$175

この2つだけで、何もしなくても月$240前後になります。ほかにも AWS Secrets Manager(シークレット単位)、AWS KMSカスタマー管理キー(キー単位)、WAF が月額で積み上がります。構成全体の正確な総額までは計算していません。

公平のために補足します。

  • Neptune には新規利用者向けに30日間750時間の無料トライアルがあります
  • OpenSearch Serverless の料金ページには、NextGenコレクションは最小OCUがなく、10分アイドルでゼロになると記載されています。
  • 構成次第で OpenSearch 部分は下げられます

とはいえ「記事を読んで試しに動かしてみる」段階で、Neptune を常時起動しておくのは気が進みません。
そこで、元記事の核を残したまま常時課金を外す方針で作り直しました。

flow-ja.jpg

残したもの、削ったもの

ブログどおりに残した部分

フロントエンド・Cognito・WAF・WebSocketは元記事どおりにしました。

  • React(Vite+TypeScript)を S3+CloudFront(OAC)で配信
  • AWS WAF は CommonRuleSet と、IPごと5分1000リクエストのレート制限
  • Amazon Cognito はセルフサインアップ無効、Liteプラン、SRP認証
  • API Gateway REST(Cognitoオーソライザー)→ Lambda dfmeaapi → Step Functions StartExecution
  • API Gateway WebSocket は $connect でIDトークンを検証し、接続を DynamoDB に保存して進捗イベントをpushします。取りこぼしは GET events?after=seq で補完します

置き換えた部分

  • オントロジー: Neptune の代わりに、S3上のTTLファイル(バージョニング有効)を rdflib で読みます
  • エージェント: Strands Agents SDK の「Agents as Tools」で、分析エージェント(Claude Sonnet 4.6)と専門エージェント2つ(故障モード、構造。Claude Haiku 4.5)を構成しました。AgentCore Runtime は使わず、Lambda 上で実行します
  • HITL: 4ゲートを1か所に減らし、レビュー単位で承認か却下を選ぶ形にしました
  • データ: DynamoDB は Reviews と Connections の2テーブルです。
  • 所見は DynamoDB に置き、ステート間ではIDだけを渡します

Step Functions(Standard)のステートは次の流れです。

  1. PinOntology: 使うオントロジーのバージョンを固定
  2. Analyze: エージェントが所見を生成
  3. Validate: オントロジーで所見を検証
  4. HitlGate: 信頼度0.6未満の所見があれば waitForTaskToken で最大24時間停止
  5. Finalize: レポートを確定

全タスクに Catch を付け、失敗時は NotifyFailure に流します。

省略した部分

  • Amazon Textract、Amazon A2I、Amazon SageMaker、MLによる事前スクリーニング
  • SQSによるA2A通信、四半期ごとの規格取り込み
  • OpenSearch Serverless と Bedrock Knowledge Bases
  • AWS Secrets Manager、AWS KMSカスタマー管理キー

オントロジーは約58ノードです。
22MnB5(ホットスタンプ用の鋼材)、ホットスタンプ、オーステナイト化→水素吸収→水素脆化→HAZ遅れ破壊→シートベルトアンカー引き抜け、スポット溶接の残留応力などを入れました。
デモ用に簡略化したもので、実データではありません。

architecture-ja.jpg

オントロジー検証は LLM ではなくコードで判定する

元記事の「オントロジースレッド」を再現するために、Validate ステートでは LLM を使わず、コードで決定的に判定しています。
これをやる理由は以下の3種類です。

  • UNRESOLVED_IRI: 所見のIRIが期待するクラス(部品、故障モード、影響、原因)に解決できない
  • BROKEN_CAUSAL_PATH: 原因→故障モード→影響の隣接ペアに、オントロジー上の直接の辺がない
  • COMPONENT_MISMATCH: その故障モードが、対象の部品で起きると定義されていない

判定の中心部分は次のとおりです(backend/src/dfmea/ontology/validate.py から抜粋)。

chain = cause_path + [fm, effect]
for i in range(len(chain) - 1):
    if not edge_ok(store, chain[i], chain[i + 1], first=(i == 0)):
        return _result("rejected", BROKEN_CAUSAL_PATH, f"no direct edge {chain[i]} -> {chain[i + 1]}")

if (URIRef(fm), DFM.occursAt, URIRef(comp)) not in store.graph:
    return _result("rejected", COMPONENT_MISMATCH, f"{fm} does not occurAt {comp}")

弾かれた所見は捨てずに、レポートの別枠に表示します。

実際に弾かれた例

動かしてみると、LLM の所見は実際に弾かれました。

  • 因果パスに、オントロジー上に存在しない辺(InsufficientQuenchRate → HAZDelayedFracture)が含まれていた所見が BROKEN_CAUSAL_PATH で除外されました
  • 中国語で実行したレビューでは、5件中3件が COMPONENT_MISMATCH で除外されました。別の部品で起きる故障モードを、対象部品の所見として出していました

LLM の出力をオントロジーの辺で機械的に照合するという元記事の考え方は、Neptune を使わない構成でも役割を果たしています。

バージョン固定を確かめる

元記事の version-pinning は、S3のバージョニングで再現しました。
PinOntology ステートで、その時点のTTLファイルの versionId と sha256 を DynamoDB に記録し、以降のステートは必ずその versionId を読みます。

head = aws.s3().head_object(Bucket=bucket, Key=key)
version_id = head["VersionId"]
store = OntologyStore.from_s3(aws.s3(), bucket, key, version_id)

確認は次の手順で行いました。

  1. オントロジー1.0.0でレビューを開始し、HITLゲートで止める
  2. 止まっている間に、S3上のTTLを新バージョン(1.1.0)に差し替える
  3. 承認してレビューを完了させる
  4. 新しいレビューを開始する

結果、止めていたレビューは1.0.0のまま完了し、次のレビューは1.1.0を使いました。
途中でオントロジーを更新しても、進行中のレビューの判定基準は変わりません。

4言語に対応する

日本語・英語・アラビア語(右から左に書くRTL)・中国語簡体字の4言語に対応しました。
対象は3つです。

  • UI
  • AI出力(根拠と推奨対策を、レビュー作成時に選んだ言語で生成)
  • オントロジーのラベル

アラビア語と中国語の訳は、ネイティブの方に確認してもらっていません。

実測値

1回のレビューの実測値です。

  • 分析: 42〜55秒
  • エンドツーエンド: 約50〜74秒
  • トークン数: 2.4万〜5.3万
  • 中国語を指定した1回だけ、202秒かかりました

セキュリティ面の確認結果です。

  • 未認証のREST・WebSocketは401
  • 別ユーザーのレビューを取得すると404

テストは pytest が63件、CDK の jest が7件です。

まだ確かめていないこともあります。

  • Throttling時のリトライと、HITLの24時間タイムアウトは単体テストのみで、実環境では試していません
  • 1レビューあたりのドル建てコストは計測していません

冒頭の問いへの答え: アイドル時は約$7/月

冒頭で心配したコストに戻ります。軽量版を何もせず置いておいたときの費用は 約$7/月 です。
内訳は WAF の WebACL が$5、ルール2本が$2です。

それ以外はほぼゼロです。

  • DynamoDB オンデマンド
  • AWS Lambda、AWS Step Functions、Amazon API Gateway
  • Amazon Cognito(Liteプラン)
  • CloudFront・S3(少量)

元記事の構成では Neptune と OpenSearch Serverless(クラシック)の最小構成だけで月$240前後かかる見込みでした。
常時起動のリソースを外したことで、アイドル時の費用はほぼWAFの分だけになりました。
使うときだけ Bedrock のトークン代などの従量課金が乗ります。

削除手順

試し終わったら、CDKのスタックをまとめて削除します。

cd infra && npx cdk destroy DfmeaSiteDeploy DfmeaBackend DfmeaWeb DfmeaWaf

DynamoDB テーブル、S3 バケット、ロググループ、Cognito の User Pool はすべて削除される設定(RemovalPolicy.DESTROY)にしてあります。

最後まで読んでいただきありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?