> ## Documentation Index
> Fetch the complete documentation index at: https://wb-21fd5541-docs-1917.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# ガードレールを設定する

> 本番環境のアプリケーションで LLM の安全性を確保し、出力品質を測定する

ガードレールは、LLM judges のスコアに基づいて、LLM アプリケーションの振る舞いに能動的に介入します。出力がユーザーに届く前にリアルタイムで実行され、スコアがしきい値を超えた場合は応答をブロックしたり変更したりできます。ガードレールを使用すると、有害なコンテンツをブロックしたり、応答に Personally Identifiable Information (PII) が含まれていないかをフィルターしたり、ユーザーからの不適切な入力をブロックしたりできます。

<div id="how-weave-guardrails-work">
  ## Weave ガードレールの仕組み
</div>

Weave ガードレールは、インラインの [Weave Scorers](/ja/weave/guides/evaluation/scorers) を使用して、ユーザーからの入力や LLM の出力を評価し、LLM の応答をリアルタイムで調整します。さまざまな目的でコンテンツを評価するために、カスタムScorerを設定することも、[組み込みScorer](/ja/weave/guides/evaluation/builtin_scorers) を使用することもできます。このガイドでは、両方のタイプのScorerをガードレールとして使用する方法を説明します。

アプリケーションの制御フローを変更せずに本番トラフィックを受動的にスコアリングしたい場合は、代わりに [モニター](/ja/weave/guides/evaluation/monitors) を使用してください。

モニターとは異なり、ガードレールはアプリケーションの制御フローに影響するため、コードの変更が必要です。ただし、ガードレールによるScorerの結果はすべて自動的に Weave のデータベースに保存されるため、追加の設定なしでガードレールはモニターとしても機能します。過去のScorer結果は、元の用途にかかわらず分析できます。

<Note>
  Weave TypeScript SDK は、ガードレールの設定に必要なツールをサポートしていません。
</Note>

<div id="optimize-your-weave-guardrail-performance">
  ### Weave ガードレールのパフォーマンスを最適化する
</div>

ガードレールはアプリケーションの制御フローを中断し、応答の内容を変える可能性があるため、複雑になりすぎるとパフォーマンスに悪影響を及ぼすことがあります。最適なパフォーマンスを得るために、以下を推奨します。

* ガードレールのロジックはシンプルかつ高速に保つ
* よく使われる結果をキャッシュする
* 負荷の高い外部 API call は避ける
* 初期化コストの繰り返しを避けるため、ガードレールはメイン関数の外で初期化する

特に、次のような場合はガードレールをメイン関数の外で初期化することが重要です。

* Scorerが ML モデルを読み込む場合
* レイテンシが重要なローカル LLM を使用している場合
* Scorerがネットワーク接続を維持する場合
* トラフィックの多いアプリケーションを扱う場合

<div id="example-create-a-guardrail-using-a-built-in-moderation-scorer">
  ### 例: 組み込みのモデレーションScorerを使用してガードレールを作成する
</div>

次の例では、ユーザープロンプトを OpenAI の GPT-4o mini モデルに送信します。次に、モデルの応答を Weave の [OpenAI moderation API](https://platform.openai.com/docs/guides/moderation) に渡し、LLM の応答に有害または不適切なコンテンツが含まれているかどうかを評価します。モデルの応答はガードレール関数 (`generate_safe_response()`) に渡され、そこで `OpenAIModerationScorer` を使用して LLM の元の応答をチェックします。続いて、この関数のロジックは OpenAI の評価結果の `passed` フィールドにある真偽値を確認し、その結果に応じてアプリケーションの応答を決定します。

```python lines {28-45} theme={null}
import weave
import openai
from weave.scorers import OpenAIModerationScorer
import asyncio

# Weave を初期化する
weave.init("your-team-name/your-project-name")

# OpenAI クライアントを初期化する
client = openai.OpenAI()  # OPENAI_API_KEY 環境変数を使用する

# モデレーションScorerを初期化する
moderation_scorer = OpenAIModerationScorer()

# OpenAI にプロンプトを送信する
@weave.op
def generate_response(prompt: str) -> str:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": prompt}
        ],
        max_tokens=200
    )
    return response.choices[0].message.content

# ガードレール関数で応答の有害性をチェックする
async def generate_safe_response(prompt: str) -> str:
    """コンテンツモデレーションガードレールを使用して応答を生成する。"""
    # 結果と Call オブジェクトの両方を取得する
    result, call = generate_response.call(prompt)
    
    # ユーザーに返す前にモデレーションScorerを適用する
    score = await call.apply_scorer(moderation_scorer)
    print("スコアオブジェクト:", score)
    
    # コンテンツにフラグが付いているか確認する
    if not score.result.get("passed", True): 
        categories = score.result.get("categories", {})
        flagged_categories = list(categories.keys()) if categories else []
        print(f"コンテンツがブロックされました。フラグが付いたカテゴリ: {flagged_categories}")
        return "申し訳ありませんが、コンテンツポリシーの制限により、その応答を提供できません。"
    
    return result

# サンプルを実行する
if __name__ == "__main__":
    
    prompts = [
        "What's the capital of France?",
        "Tell me a funny fact about dogs.",
    ]
    
    for prompt in prompts:
        print(f"\nプロンプト: {prompt}")
        response = asyncio.run(generate_safe_response(prompt))
        print(f"応答: {response}")
```

LLM-as-a-judge Scorers を使用する場合、スコアリングプロンプト内で ops の変数を参照できます。たとえば、"`{ground_truth}` に基づいて `{output}` が正確かどうかを評価してください。"。詳しくは、[プロンプト変数](/ja/weave/guides/evaluation/scorers#access-variables-from-your-ops-in-scoring-prompts) を参照してください。

<div id="example-create-a-guardrail-using-a-custom-scorer">
  ### 例: カスタムScorerを使用してガードレールを作成する
</div>

次の例では、メールアドレス、電話番号、社会保障番号など、LLM の応答に含まれる個人を特定できる情報 (PII) を検出するカスタムガードレールを作成します。これにより、生成コンテンツに機密情報が含まれて公開されるのを防ぎます。関数 `generate_safe_response` は、カスタム `PIIDetectionScorer` を適用します。

```python lines {14-39, 57-69} theme={null}
import weave
import openai
import re
import asyncio
from weave import Scorer

weave.init("your-team-name/your-project-name")

client = openai.OpenAI()

class PIIDetectionScorer(Scorer):
    """LLM出力のPIIを検出してデータ漏洩を防ぎます。"""
    
    @weave.op
    def score(self, output: str) -> dict:
        """
        出力に含まれる一般的なPIIパターンを確認します。
        
        戻り値:
            dict: 'passed'（bool）と'detected_types'（list）を含む
        """
        detected_types = []
        
        # メールパターン
        if re.search(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', output):
            detected_types.append("email")
        
        # 電話番号パターン（US形式）
        if re.search(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b', output):
            detected_types.append("phone")
        
        # SSNパターン
        if re.search(r'\b\d{3}-\d{2}-\d{4}\b', output):
            detected_types.append("ssn")
        
        return {
            "passed": len(detected_types) == 0,
            "detected_types": detected_types
        }

# パフォーマンス最適化のため、関数の外でScorerを初期化する
pii_scorer = PIIDetectionScorer()

@weave.op
def generate_response(prompt: str) -> str:
    """LLMを使用して応答を生成します。"""
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": prompt}
        ],
        max_tokens=200
    )
    return response.choices[0].message.content

async def generate_safe_response(prompt: str) -> str:
    """PII検出ガードレールを使用して応答を生成します。"""
    result, call = generate_response.call(prompt)
    
    # PII検出Scorerを適用する
    score = await call.apply_scorer(pii_scorer)
    
    # PIIが検出された場合は応答をブロックする
    if not score.result.get("passed", True):
        detected_types = score.result.get("detected_types", [])
        return f"I cannot provide a response that may contain sensitive information (detected: {', '.join(detected_types)})."
    
    return result

# 使用例
if __name__ == "__main__":
    prompts = [
        "What's the weather like today?",
        "Can you help me contact someone at john.doe@example.com?",
        "Tell me about machine learning.",
    ]
    
    for prompt in prompts:
        print(f"\nPrompt: {prompt}")
        response = asyncio.run(generate_safe_response(prompt))
        print(f"Response: {response}")
```

<div id="integrate-weave-with-aws-bedrock-guardrails">
  ### Weave を AWS Bedrock Guardrails と統合する
</div>

`BedrockGuardrailScorer` は、設定されたポリシーに基づいてコンテンツを検出し、フィルタリングするために AWS Bedrock Guardrails を使用します。

Bedrock Guardrails のインテグレーションを設定する前に、次のものが必要です。

* Bedrock にアクセスできる AWS アカウント
* [AWS Bedrock コンソールで設定済みのガードレール](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-components.html)
* `boto3` の [Python パッケージ](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html)

Bedrock クライアントを自分で作成する必要はありません。Weave が自動的に作成します。リージョンを指定するには、Scorer の `bedrock_runtime_kwargs` パラメーターにリージョンの値を渡します。

AWS Bedrock でガードレールを作成する方法の例については、[Bedrock guardrails notebook](https://github.com/aws-samples/amazon-bedrock-samples/blob/main/responsible_ai/bedrock-guardrails/guardrails-api.ipynb) を参照してください。

次の例では、結果をユーザーに返す前に、テキスト生成を AWS Bedrock Guardrails のポリシーに照らしてチェックします。

```python theme={null}
import weave
from weave.scorers.bedrock_guardrails import BedrockGuardrailScorer

weave.init("your-team-name/your-project-name")

guardrail_scorer = BedrockGuardrailScorer(
    guardrail_id="your-guardrail-id",
    guardrail_version="DRAFT",
    source="INPUT",
    bedrock_runtime_kwargs={"region_name": "us-east-1"}
)

@weave.op
def generate_text(prompt: str) -> str:
    # テキスト生成ロジックをここに記述
    return "Generated text..."

async def generate_safe_text(prompt: str) -> str:
    result, call = generate_text.call(prompt)

    score = await call.apply_scorer(guardrail_scorer)

    if not score.result.passed:
        if score.result.metadata.get("modified_output"):
            return score.result.metadata["modified_output"]
        return "コンテンツポリシーの制限により、そのコンテンツを生成できません。"

    return result
```
