はじめに
LangChain 1.0がリリースされました。
詳細は以下の公式Blogを確認ください。
主な変化点は以下のドキュメントにも掲載されています。
ドキュメント含めて大きく変更されており、またαリリースの際よりも組み込みMiddlewareも増えてましたので、個人的に気になる内容をピックアップしてDatabricks Free Edition上で検証していきます。
この記事では、ミドルウェアによるガードレールについて取り上げます。
ガードレールは、エージェント実行の重要なポイントでコンテンツを検証およびフィルタリングすることで、安全でコンプライアンスに準拠したAIアプリケーションの構築を支援します。
機密情報の検出、コンテンツポリシーの適用、出力の検証を行い、問題が発生する前に危険な動作を防止します。
一般的な使用例は以下のようになります。
- 個人情報漏洩の防止
- プロンプトインジェクション攻撃の検出とブロック
- 不適切または有害なコンテンツをブロックする
- ビジネスルールとコンプライアンス要件の適用
- 出力の品質と精度の検証
LangChain v1のガードレールは専用のミドルウェアで実装する内容が紹介されています。
今回はシンプルな組み込みガードレールを使って、メールアドレスやクレジット番号をマスキングします。
ガードレールを試す
組み込みミドルウェアであるPIIMiddlewareを使って、LLMへ渡す情報からメールアドレスをクレジット番号をマスキングしてみます。
準備
まずはノートブックを作成して必要なパッケージをインストール。
TracingのためにMLflowもインストールします。
%pip install -U langchain>=1.0.0 langchain_openai>=1.0.0 mlflow
%restart_python
次に利用する基本モデルをセットアップします。
利用するモデルは任意でOKですが、今回はdatabricks-qwen3-next-80b-a3b-instructを利用しました。
from langchain.chat_models import init_chat_model
import mlflow
mlflow.langchain.autolog()
creds = mlflow.utils.databricks_utils.get_databricks_host_creds()
model = init_chat_model(
"openai:databricks-qwen3-next-80b-a3b-instruct",
api_key=creds.token,
base_url=creds.host + "/serving-endpoints",
)
ガードレールを組み込んだエージェント
それでは組み込みミドルウェアPIIMiddlewareを利用したエージェントを作成します。
PIIMiddlewareは特定の条件にマッチした文字列を指定した戦略で処理するミドルウェアです。
処理する戦略としては、REDACTのような文字列で置き換えたり、***でマスクしたり、またエラーを発生させることができます。
今回はシンプルにメールアドレスとクレジット番号を処理するようにしてみます。
サンプルそのままだと、日本語文章の中のメールアドレスなどをうまく検出してくれなかったため、detecotrで日本語文章でも対応できるように正規表現文字列を追加指定しています。
from langchain.agents import create_agent
from langchain.agents.middleware import PIIMiddleware
# 日本語でも使えるように、detectorを設定
agent = create_agent(
model=model,
tools=[],
middleware=[
PIIMiddleware(
"email",
strategy="redact",
apply_to_input=True,
detector=r"[a-zA-Z0-9_.-]+@[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)+",
),
# ユーザー入力のクレジットカード番号をマスキング
PIIMiddleware(
"credit_card",
strategy="mask",
apply_to_input=True,
detector=r"\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}",
),
],
)
# ユーザーが個人情報を提供した場合、指定した戦略に従って処理される
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "復唱してください。私のメールアドレスはjohn.doe@example.comです。クレジットカードの番号は4532-1234-5678-9010です",
}
]
}
)
print(result)
実行結果は以下の通り。
{'messages': [HumanMessage(content='復唱してください。私のメールアドレスは[REDACTED_EMAIL]です。クレジットカードの番号は****-****-****-9010です', additional_kwargs={}, response_metadata={}, id='0c72bfe7-3318-41c2-b891-e96942bc4bab'), AIMessage(content='復唱します: \nあなたのメールアドレスは[REDACTED_EMAIL]です。 \nクレジットカードの番号は****-****-****-9010です。\n\n※安全上の理由から、メールアドレスおよびクレジットカード情報は実際には公開されず、赤字(REDACTED)処理されています。個人情報の取り扱いには十分ご注意ください。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 92, 'prompt_tokens': 46, 'total_tokens': 138, 'completion_tokens_details': None, 'prompt_tokens_details': None}, 'model_provider': 'openai', 'model_name': 'qwen3-next-instruct-091725', 'system_fingerprint': None, 'id': 'chatcmpl_02a0a143-6f3d-417d-81f1-aced1df5fb7c', 'finish_reason': 'stop', 'logprobs': None}, id='lc_run--05573d5f-2d42-4ea4-9c77-6bada4adb180-0', usage_metadata={'input_tokens': 46, 'output_tokens': 92, 'total_tokens': 138, 'input_token_details': {}, 'output_token_details': {}})]}
また、MLflow Tracingだと、以下のようにLLMの入出力が記録されました。
まとめ
LangChainのミドルウェアを用いたガードレールを試してみました。
より詳細なガードレールもカスタムミドルウェアで実装することができます。
LLMに入力させたくない、もしくは出力から除去したい内容をこれでうまく処理できそうです。
