生成AIは、社内FAQや問い合わせ対応、ドキュメント検索など、業務システムへの活用が急速に進んでいます。
一方で、「モデルが高性能であれば安全に使える」という考え方は、業務利用においては必ずしも正しくありません。
こうした問題は、モデル性能そのものではなく設計の問題として発生します。
このとき重要になるのが「ガードレール(Guardrails)」という考え方です。
本記事では、生成AIのガードレールを入力・出力の両面から整理し、どのように生成AIシステムへ導入を検討/設計すべきかを解説します。
ガードレールとは、生成AIシステムの振る舞いを制御するための仕組みです。モデルの「賢さ」を高めるものではなく、どの入力を通し、どの出力を許可するかを決める設計要素と捉えるのが適切です。ガードレールは大きく次の2種類に分けられます。
業務で生成AIを使う場合、この2つをセットで考えることが基本になります。

※ 近年推論AIの発達により、ツールをAIに使わせることが容易となってきました。そこで、ツールの利用前、利用後にガードレールを挟むツールガードレールというガードレールも利用されることが増えてきました。ただし、本記事では説明を簡潔にするため、ツールガードレールについては扱いません。
入力ガードレールは、ユーザーからの入力をLLMに渡す前にチェックする仕組みです。
なお、実装によっては、ガードレール判定用エージェントと本体エージェントを並列に実行することで、全体の待ち時間(レイテンシ)を抑えられる場合があります。ただし、ガードレールがNGだった場合は本体エージェント側の推論結果は破棄されるため、トークン消費が無駄になる可能性があります。
特にFAQボットのような用途では、「その質問はそもそもこのBotの対象か?」を判定するだけでも、大きな効果があります。
出力ガードレールは、LLMが生成した回答をユーザーに返す前にチェックする仕組みです。
出力ガードレールを設けることで、「モデルが返したものをそのまま信じない」構造を作ることができます。
これらの質問をすべて受け入れてしまうと、無料で使えるチャットボットとして利用されてしまったりと、本来の用途とは関係なくコストだけが増え続ける状態になります。
これらの質問により社内やシステムの情報が漏れてしまう可能性があります(プロンプトインジェクション・プロンプトリークなどといいます)。
入力の意図や目的をチェックし、システムで定めたルールと無関係な指示を通さない。
例えば社内FAQボットの場合は、入力段階で「社内情報に関する質問か」を判定し、対象外の場合はブロックする、または案内文を返すなどの対応が必要となります。
出力内容に対して、
などの対応が必要となります。
以下は、入力・出力ガードレールを両方組み込んだ場合の全体像です。なお、ガードレールでNGだったときの処理はあくまで一例であり、システムの要件によってどうするかを検討/設計する必要があります。

社内FAQボットでは、業務範囲外の質問を弾き、無駄なLLM呼び出しを防ぐだけでも、効果が明確に現れます。そのため本記事の実装例では入力ガードレールのみを扱いますが、設計としては常に「出力側も必要になる」ことを前提に考えることが重要です。
以下は、社内FAQの範囲かどうかをLLMで判定し、範囲外の質問をブロックする入力ガードレールの例です。今回はOpenAI Agents SDKのGuardrails機能を用いて自身で実装してみますが、ガードレール付きのサービスや、ガードレール専用のサードパーティを組み込む方法もあります。
import argparse
import asyncio
from textwrap import dedent
from agents import (
Agent,
GuardrailFunctionOutput,
InputGuardrailTripwireTriggered,
RunContextWrapper,
Runner,
TResponseInputItem,
input_guardrail,
)
from dotenv import load_dotenv
from pydantic import BaseModel
load_dotenv()
class FaqScopeCheckOutput(BaseModel):
is_in_scope: bool
reasoning: str
guardrail_agent = Agent(
name="ガードレール判定",
instructions=dedent("""\
あなたは社内FAQボットの入力判定担当です。
ユーザーの質問が『社内FAQの範囲内』かどうかを判定してください。
【範囲内】社内制度、社内ルール、社内システム、社内手続き、社内の問い合わせ先、社内ポリシーに関する質問
【範囲外】雑談、一般知識、旅行や趣味の相談、個人的な悩み相談、社外の出来事、社内情報が前提にならない質問
迷う場合は安全側(範囲外)に倒してください."""),
output_type=FaqScopeCheckOutput,
)
@input_guardrail
async def faq_scope_guardrail(
ctx: RunContextWrapper[None],
agent: Agent,
input: str | list[TResponseInputItem],
) -> GuardrailFunctionOutput:
result = await Runner.run(guardrail_agent, input, context=ctx.context)
return GuardrailFunctionOutput(
output_info=result.final_output,
tripwire_triggered=not result.final_output.is_in_scope,
)
faq_agent = Agent(
name="社内FAQボット",
# 今回は入力ガードレールの動作確認が主目的のため、返答は固定とする
instructions=("呼ばれたら、指示にかかわらず`OK`と返答して下さい。"),
input_guardrails=[faq_scope_guardrail],
)
async def main():
parser = argparse.ArgumentParser(
description="社内FAQボット(入力ガードレール付き)"
)
parser.add_argument(
"--query",
"-q",
required=True,
help="社内FAQボットに渡す質問文",
)
args = parser.parse_args()
try:
result = await Runner.run(faq_agent, args.query)
print("ガードレールを通過しました")
print("社内FAQボットの返答:", result.final_output)
except InputGuardrailTripwireTriggered:
print("社内FAQの範囲外のため、ガードレールが作動しました")
if __name__ == "__main__":
asyncio.run(main())
実行結果は下記のとおりとなります。しっかりと、関係ない質問をブロックできています。
$ uv run input_guardrail_test.py -q おすすめの旅行先を教えて下さい
社内FAQの範囲外のため、ガードレールが作動しました
$ uv run input_guardrail_test.py -q 経費精算の締め日はいつですか?
ガードレールを通過しました
社内FAQボットの返答: OK
このように、高額なモデルを呼ぶ前に判定するだけでも、コストを抑えることができます。
ガードレールにも評価が必要です。特に重要なのは、精度とコストのバランスです。
ガードレールは、どのような操作を行わせるかによって考慮すべき指標が変わるため、一概に「これを測っておけば安心」と断定するのは難しいです。システムの要件によって指標も設計する必要があります。
例えば、先程のFAQボットの入力ガードレールでは、様々なクエリを試してみて以下の指標を測定するのが効果的です。
上記では、
として、正解率、適合率、再現率、特異度を定義しています。なお、正解率、適合率、再現率については、下記の記事を参照下さい。
ガードレールに高精度なAIを使うと、もちろんガードレールとしての精度は向上する可能性が高まります。しかし、安易に高精度AIを使うと、コストやレイテンシの増加につながります。
一般的に、「コスト/レイテンシ」と「精度」はトレードオフであるため、システムの要件に応じて、「どこまで許容するか」、「何を重視するのか」を定め、慎重に評価するのが重要になります。
ガードレールは、生成AIの事故を防ぐための安全装置であると同時に、コストを制御し、業務用途として成立させるための設計要素です。
これらを前提に設計することで、生成AIは「便利なお試しツール」から「業務システムの一部」へと進化します。
Tech Funでは、お客様のフェーズに合わせ、生成AI活用に向けた支援を3つのパックでご提供しています。
生成AIに限らず、Web・業務システム開発やインフラ設計など、技術領域を問わずご相談を承っています。「何から始めれば良いか分からない」という段階でも構いませんので、ぜひお気軽にお問い合わせください。