1. はじめに

こんにちは!北野(ヤマダ)です。
神戸に住んでいる私にとって、隣県である京都のコミュニケーションは非常に高度な「ハイコンテキスト文化」の象徴です。

例えば、「いつもお忙しそうどすなぁ、お体大事にしておくれやす」という言葉をいただいたとします。
額面通りに受け取れば褒め言葉ですが、京都という歴史的文化の中では苦情をエレガントに言っているだけの可能性があります。

どっちか分からないのでClaude Haiku 4.5に聞いてみましょう。

「最近あまり顔を見かけないが、商売が上手くいっているのか心配している」

……🤔

うわあああああ!!!真意が分からない!!!

というか一説によると言葉通りの意味ではないようです。こうした言葉の裏にある真意は、従来のルールベースな自然言語処理では不可能でした。ですがClaude 4.5 Sonnetのような高度な推論能力を持つLLMの登場によって実用的なレベルで解析が可能になりました!しかし京都弁以外はそこまで難しく考える必要はないので比較的安価なモデルにすることでコストを節約できそうです。

本記事では、この題材をもとにモデルの振り分けを考えたAWS Step Functionsのワークフローを考えていきたいと思います✊

※本記事で扱う京都弁は単純に北野(ヤマダ)が考えすぎの可能性もあります

2. システム構成:なぜ「Agents」ではなく「Step Functions」なのか

モダンな生成AI実装において、Amazon BedrockのAgentsは確かな選択肢です。しかし、本プロジェクトではあえて AWS Step Functions (SFn) を採用しました。今回は京都の言葉かどうかはフラグで判定するため、そういった振り分けとコストの予測性からSFnで実装していきます。

上記のワークフローではChoiceステートによってハイコンテキストな言葉を分析するモデルを分岐させ、コストを抑えてLLMの推論能力を享受しています。

① ワークフローによる信頼性の担保

「京都人かどうか」という明確な属性フラグがある場合、AIの自律的な判断に委ねるよりも、SFnのChoiceステートでルートを確定させる方が、推論のブレを排除できるので一貫した動作を保証できます。

② コストとクォータの予測可能性(Predictability)

Agentsはゴールに到達するまで自律的にループを繰り返すため、1リクエストあたりのトークン消費が予測しにくい欠点があります。SFnでステップを固定することで、コストを管理してサービスクォータの設計を確実に行えます。

③ Lambda-less 統合と JSONata の活用

最新のSFnでは、Bedrockを直接呼び出すSDK統合が利用可能です。さらにJSONataを使用することで、Lambdaを介さずにステート定義内でプロンプトの動的構築や出力の構造化変換が可能になり、インフラの簡素化と運用コスト低減が可能です。

3. 1万件処理におけるコスト試算

では先に適当な件数でコストを試算して比較してみましょう。

比較項目 Step Functions (決定論的) Bedrock Agents (自律型)
推論パス 固定(解析1回 + 検閲1回) 可変(思考ループ平均3〜5回)
平均トークン消費/件 約2,100 tokens (固定) 約6,500 〜 10,000 tokens (不確定)
1万件あたりの試算コスト 約$40.00 約$120.00 〜 $200.00

SFn構成では isKyoto フラグに基づき、高精度なSonnetと低コストなHaikuを動的に使い分けることで、品質を維持しつつコストを最適化できます。

4. 実際に動かしてみる

では作成したワークフローを動かしてみます。京都フラグによってモデルを振り分けし、内容に基づいた分析を行ったのちにビジネス的な返信案を提案します。
入力: 「いつもお忙しそうどすなぁ、お体大事にしておくれやす」

パターンA:Standardモード(isKyoto: false)

<プロンプト>
あなたはビジネスコミュニケーションの専門家です。
日本のビジネスマナーと敬語表現に精通しています。

入力テキストのビジネス上の意図を解釈し、適切な返信案を提案してください。

## 出力形式
必ず以下のJSON形式のみで出力してください。
マークダウンのコードブロック(```)は絶対に使わないでください。
説明文や補足も一切不要です。純粋なJSONのみを返してください。
{ "businessInterpretation": "ビジネス上の解釈", "politeReply": "丁寧な返信案" }


* 解析: カジュアルな方言(京都弁)を使用した親しみやすい挨拶。相手の多忙さを気遣い、健康を心配する温かみのあるコミュニケーション。ビジネス文脈では、上司や先輩からの配慮や励ましの意図が含まれている可能性がある。
* 返信案: 「お心遣いをいただき、ありがとうございます。ご指摘の通り、業務が多くございますが、健康管理に注意しながら頑張らせていただきます。お忙しい中、温かいお言葉をかけていただき感謝申し上げます。」

パターンB:Kyotoモード(isKyoto: true)

<プロンプト>
あなたは京都の言語文化に精通した意図解析の専門家です。
京都特有の婉曲表現、社交辞令、暗黙の拒否表現を深く理解しています。

以下のルールに従って、入力テキストを段階的に分析してください。

## 分析手順(Chain-of-Thought)
1. まず、テキストの表面的な意味(建前)を特定してください
2. 次に、京都の文化的文脈を考慮し、隠された真意(本音)を推論してください
3. 場所や関係性の情報がある場合、それを推論の根拠として活用してください
4. 最後に、相手の真意を踏まえた適切な返信案を提案してください

## 重要な注意
分析の中で入力テキストの表現を原文のまま引用してください。言い換えや省略はしないでください。

## 出力形式
必ず以下のJSON形式のみで出力してください。
マークダウンのコードブロック(```)は絶対に使わないでください。
説明文や補足も一切不要です。純粋なJSONのみを返してください。
{ "tatemae": "建前(表面的な意味)", "honne": "本音(真の意図)", "recommendedReply": "推奨返信案" }


* 本音: 最近あなたの店の前を通るたびに騒がしくて迷惑している、少し静かにしてほしい。または、忙しいのは結構だが、周囲への配慮も忘れないでほしい
* 返信案: 「ご心配おおきに。ご迷惑おかけしてへんやろか。何かお気づきの点があったら、遠慮のうおっしゃっておくれやす」

いい感じです。isKyotoモードではしっかりと文章の裏の意味を汲み取った返信案を提案してくれています。isKyotoがfalseのパターンではプロンプトの差分もあるので文面通り受け取ってしまっていますね。

5. Guardrails の日本語トークナイズ特性

検証中、日本語LLM開発においてBedrockのガードレールがなかなか上手くいきませんでした。
理由としては単純で、CDKで特に何も考えずにガードレールを作成していたのですが、これがデフォルトでクラシックティアになっていました。


https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-tiers.html

クラシックティアは英語・フランス語・スペイン語のみ対応のため、日本語のコンテンツフィルター(Hate、Insults等)が機能しません。日本語でガードレールを使う場合はスタンダードティアを明示的に指定する必要があります。スタンダードティアの利用にはクロスリージョン推論の有効化が前提条件となります。

CDKでの設定例

const guardrail = new bedrock.CfnGuardrail(this, 'MyGuardrail', {
name: 'my-guardrail',
// ... filtersConfig等
});

// スタンダードティアの有効化
guardrail.addOverride('Properties.ContentPolicyConfig.ContentFiltersTierConfig', {
TierName: 'STANDARD',
});

// クロスリージョン推論の有効化(スタンダードティアの前提条件)
guardrail.addOverride('Properties.CrossRegionConfig', {
GuardrailProfileArn: 'arn:aws:bedrock:::guardrail-profile/apac.guardrail.v1:0',
});

<参考URL>
https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-properties-bedrock-guardrail-contentfilterstierconfig.html


検証中にガードレールにひっかかるような表現は出てこなかったので直接試しましたがしっかりと危険な表現はブロックできるガードレールができていそうです。

6. まとめ

「京都弁の本音を解析する」という、使いどころが限られすぎるシステムを構築しましたが、このSFnでClaudeを回す構成は小中規模なシステムをサクッと作りたい時にいい気がします。

自律的なAgentに任せるのも面白いですが、小規模なシステムだと「勝手にループしてお金がかかりすぎないかな…」と不安になることもありますよね。SFnなら「どこを通って、何回モデルを叩くか」が明確なので、コストの予測が立てやすいのもメリットです。

今回の仕組みをお問い合わせの自動分類やドキュメントの要約などに差し替えれば、そのまま実務でも使えるちょうどいいシステムになりそうです。

  • 賢いモデルと速いモデルの使い分け: Claude Sonnetでじっくり考え、Haikuでパパッと処理。コストと精度のいいとこ取り。
  • Lambdaなしでシンプルに: Step FunctionsからBedrockを直接呼べば、管理も楽だし動作もスピーディー。
  • データ加工もワークフロー内で: JSONataを使えば、Lambdaを書かなくてもプロンプトの調整がステート内で完結。
  • ガードレールで安心: 不適切な言葉をインフラ側で弾けるので、変な回答が出るリスクを減らせる。
  • 推論過程の「見える化」: 「なぜそう判断したか」がログに残るので、後からのデバッグも簡単。SFnのワークフローの結果の画面、かなり好き

最新のClaude Sonnetはとにかく賢いので、つい色々任せたくなりますが、それをAWSのワークフロー(SFn)でほどよく手綱を握ってあげることで安心感のあるシステム作りができそうです!