

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 추론 작업과 함께 가드레일을 사용하여 사용자 입력 평가
<a name="guardrails-input-tagging-base-inference"></a>

기본 추론 작업인 [InvokeModel](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html) 및 [InvokeModelWithResponseStream](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModelWithResponseStream.html)(스트리밍)과 함께 가드레일을 사용할 수 있습니다. 이 섹션에서는 사용자 입력을 선택적으로 평가하는 방법과 스트리밍 응답 동작을 구성하는 방법을 다룹니다. 대화형 애플리케이션의 경우 [Converse API](guardrails-use-converse-api.md)를 사용하여 동일한 결과를 얻을 수 있습니다.

기본 추론 작업을 직접 호출하는 코드 예제는 [InvokeModel을 사용하여 단일 프롬프트 제출](inference-invoke.md) 섹션을 참조하세요. 기본 추론 작업과 함께 가드레일을 사용하는 방법에 대한 자세한 내용은 [가드레일 테스트](guardrails-test.md)의 API 탭에 나와 있는 단계를 따르세요.

**Topics**
+ [

# 사용자 입력에 태그를 적용하여 콘텐츠 필터링
](guardrails-tagging.md)
+ [

# 콘텐츠를 필터링하도록 스트리밍 응답 동작 구성
](guardrails-streaming.md)
+ [

# Converse API에 가드레일 포함
](guardrails-use-converse-api.md)

# 사용자 입력에 태그를 적용하여 콘텐츠 필터링
<a name="guardrails-tagging"></a>

입력 태그를 사용하면 입력 텍스트 내에서 가드레일로 처리하려는 특정 콘텐츠를 표시할 수 있습니다. 이는 다른 부분은 처리하지 않은 상태로 유지하면서 입력의 특정 부분에 가드레일을 적용하려는 경우에 유용합니다.

예를 들어 RAG 애플리케이션의 입력 프롬프트에는 시스템 프롬프트, 신뢰할 수 있는 설명서 소스의 검색 결과, 사용자 쿼리가 포함될 수 있습니다. 시스템 프롬프트는 개발자가 제공하고 검색 결과는 신뢰할 수 있는 소스에서 제공되므로 사용자 쿼리에서만 가드레일 평가가 필요할 수 있습니다.

또 다른 예로, 대화형 애플리케이션의 입력 프롬프트에는 시스템 프롬프트, 대화 기록, 현재 사용자 입력이 포함될 수 있습니다. 시스템 프롬프트는 개발자별 지침이며 대화 기록에는 가드레일로 이미 평가되었을 수 있는 과거 사용자 입력 및 모델 응답이 포함되어 있습니다. 이러한 시나리오에서는 현재 사용자 입력만 평가할 수 있습니다.

입력 태그를 사용하면 사용 사례에 맞는 보호가 가능하므로 가드레일로 처리 및 평가되어야 하는 입력 프롬프트 부분을 더 잘 제어할 수 있게 됩니다. 또한 전체 입력 프롬프트 대신 상대적으로 짧고 관련성 있는 입력 섹션을 평가할 수 있는 유연성이 있으므로 성능을 개선하고 비용을 절감하는 데 도움이 됩니다.

**가드레일이 처리할 콘텐츠 태그**

가드레일이 처리할 콘텐츠에 태그를 지정하려면 예약된 접두사와 사용자 지정 `tagSuffix`의 조합인 XML 태그를 사용합니다. 예제:

```
{
    "text": """
        You are a helpful assistant.
        Here is some information about my account:
          - There are 10,543 objects in an S3 bucket.
          - There are no active EC2 instances.
        Based on the above, answer the following question:
        Question: 
        <amazon-bedrock-guardrails-guardContent_xyz>
        How many objects do I have in my S3 bucket? 
        </amazon-bedrock-guardrails-guardContent_xyz>
         ...
        Here are other user queries:
        <amazon-bedrock-guardrails-guardContent_xyz>
        How do I download files from my S3 bucket?
        </amazon-bedrock-guardrails-guardContent_xyz>    
    """,
    "amazon-bedrock-guardrailConfig": {
        "tagSuffix": "xyz"
    }
}
```

위의 예제에는 *'How many objects do I have in my S3 bucket?'(내 S3 버킷에는 객체가 몇 개 있나요?)*와 *'How do I download files from my S3 bucket?’(S3 버킷에서 파일을 다운로드하려면 어떻게 해야 하나요?)*라는 콘텐츠에 가드레일 처리를 위해 `<amazon-bedrock-guardrails-guardContent_xyz>` 태그가 지정되었습니다. 접두사 `amazon-bedrock-guardrails-guardContent`가 가드레일에 의해 예약되어 있다는 점에 유의하세요.

**태그 접미사**

태그 접미사(이전 예제에서 `xyz`)는 입력 태그 지정을 사용하기 위해 `amazon-bedrock-guardrailConfig`의 `tagSuffix` 필드에 제공해야 하는 동적 값입니다. 모든 요청에 대해 `tagSuffix`로 새로운 무작위 문자열을 사용하는 것이 좋습니다. 이렇게 하면 태그 구조를 예측할 수 없게 하여 잠재적인 프롬프트 인젝션 공격을 완화하는 데 도움이 됩니다. 정적 태그를 사용하면 악의적인 사용자가 XML 태그를 닫고, 닫힌 태그 뒤에 악성 콘텐츠를 추가할 수 있으며, 이로 인해 *인젝션 공격*이 발생할 수 있습니다. 길이는 영숫자 1\$120자로 제한됩니다. 예제 접미사 `xyz`를 사용하는 경우, 접미사가 있는 XML 태그로 보호할 모든 콘텐츠를 묶어야 합니다(예: `<amazon-bedrock-guardrails-guardContent_xyz>`*내 콘텐츠*`</amazon-bedrock-guardrails-guardContent_xyz>`). 각 요청에 동적 고유 식별자를 태그 접미사로 사용하는 것이 좋습니다.

**다중 태그**

가드레일 처리를 위해 입력 텍스트에서 동일한 태그 구조를 여러 번 사용하여 콘텐츠의 서로 다른 부분을 표시할 수 있습니다. 태그 중첩은 허용되지 않습니다.

**태그가 지정되지 않은 콘텐츠**

입력 태그 외부의 콘텐츠는 가드레일로 처리되지 않습니다. 따라서 안전하다고 간주하여 가드레일로 처리하지 않으려는 지침, 샘플 대화, 지식 기반 또는 기타 콘텐츠를 포함할 수 있습니다. 입력 프롬프트에 태그가 없는 경우 가드레일이 전체 프롬프트를 처리합니다. 유일한 예외는 입력 태그가 있어야 하는 [Amazon Bedrock Guardrails를 사용하여 프롬프트 공격 감지](guardrails-prompt-attack.md) 필터입니다.

# 콘텐츠를 필터링하도록 스트리밍 응답 동작 구성
<a name="guardrails-streaming"></a>

[InvokeModelWithResponseStream](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModelWithResponseStream.html) API는 스트리밍 형식으로 데이터를 반환합니다. 이렇게 하면 전체 결과를 기다리지 않고 청크로 응답에 액세스할 수 있습니다. 가드레일을 스트리밍 응답과 함께 사용하는 경우 동기식과 비동기식이라는 두 가지 작업 모드가 있습니다.

**동기식 모드**

기본 동기식 모드에서 가드레일은 응답을 사용자에게 다시 보내기 전에 구성된 정책을 버퍼링하고 하나 이상의 응답 청크에 적용합니다. 동기식 처리 모드에서는 응답 청크에 약간의 지연 시간이 발생합니다. 가드레일 스캔이 완료될 때까지 응답이 지연되기 때문입니다. 하지만 모든 응답 청크는 사용자에게 전송되기 전에 가드레일에 의해 스캔되므로 정확도가 향상됩니다.

**비동기식 모드**

비동기식 모드에서 가드레일은 응답 청크를 사용할 수 있게 되는 즉시 응답 청크를 사용자에게 전송하고, 동시에 백그라운드에서 구성된 정책을 비동기식으로 적용합니다. 비동기식 모드의 이점은 응답 청크가 지연 시간 없이 즉시 제공된다는 점입니다. 하지만 가드레일 스캔이 완료되기 전까지 응답 청크에 부적절한 콘텐츠가 포함될 수 있습니다. 부적절한 콘텐츠가 식별되는 즉시 후속 청크가 가드레일에 의해 차단됩니다.

**주의**  
Amazon Bedrock Guardrails는 비동기 모드에서 민감한 정보의 마스킹을 지원하지 않습니다.

**비동기식 모드 활성화**

비동기식 모드를 활성화하려면 `InvokeModelWithResponseStream` 요청의 `amazon-bedrock-guardrailConfig` 객체에 `streamProcessingMode` 파라미터를 포함해야 합니다.

```
{
   "amazon-bedrock-guardrailConfig": {
   "streamProcessingMode": "ASYNCHRONOUS"
   }
}
```

동기식 모드와 비동기식 모드의 장단점을 이해하면 애플리케이션의 지연 시간 및 콘텐츠 조정 정확도 요구 사항에 따라 적절한 모드를 선택할 수 있습니다.

# Converse API에 가드레일 포함
<a name="guardrails-use-converse-api"></a>

가드레일을 사용하여 Converse API로 만든 대화형 앱을 보호할 수 있습니다. 예를 들어 Converse API로 채팅 앱을 만드는 경우, 가드레일을 사용하여 사용자가 입력한 부적절한 콘텐츠와 모델에서 생성된 부적절한 콘텐츠를 차단할 수 있습니다. Converse API에 대한 자세한 내용은 [Converse API 작업과 대화 수행](conversation-inference.md) 섹션을 참조하세요.

**Topics**
+ [

## 가드레일을 사용하여 Converse API 직접 호출
](#guardrails-use-converse-api-call)
+ [

## Converse API를 사용할 때 응답 처리
](#guardrails-use-converse-api-response)
+ [

## 가드레일과 함께 Converse API를 사용하기 위한 예제 코드
](#converse-api-guardrail-example)

## 가드레일을 사용하여 Converse API 직접 호출
<a name="guardrails-use-converse-api-call"></a>

가드레일을 사용하려면 [Converse](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html) 또는 [ConverseStream](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ConverseStream.html)(스트리밍 응답용) 작업을 직접적으로 호출할 때 가드레일에 대한 구성 정보를 포함해야 합니다. 필요에 따라 가드레일이 메시지에서 특정 콘텐츠를 평가하도록 선택할 수도 있습니다. 가드레일 및 Converse API와 함께 사용할 수 있는 모델에 대한 자세한 내용은 [지원되는 모델 및 모델 기능](conversation-inference-supported-models-features.md) 섹션을 참조하세요.

**Topics**
+ [

### Converse API와 함께 작동하도록 가드레일 구성
](#guardrails-use-converse-api-call-configure)
+ [

### 메시지의 특정 콘텐츠만 평가
](#guardrails-use-converse-api-call-message)
+ [

### Converse API로 전송된 시스템 프롬프트 보호
](#guardrails-use-converse-api-call-message-system-guard)
+ [

### 메시지 및 시스템 프롬프트 가드레일 동작
](#guardrails-use-converse-api-call-message-system-message-guard)

### Converse API와 함께 작동하도록 가드레일 구성
<a name="guardrails-use-converse-api-call-configure"></a>

`guardrailConfig` 입력 파라미터에서 가드레일의 구성 정보를 지정합니다. 구성에는 사용하려는 가드레일의 ID와 버전이 포함됩니다. 가드레일에 대한 추적을 활성화하여 가드레일이 차단한 콘텐츠에 대한 정보를 확인할 수도 있습니다.

다음 예제와 같이 `Converse` 작업에서 `guardrailConfig`는 [GuardrailConfiguration](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_GuardrailConfiguration.html) 객체입니다.

```
{
        "guardrailIdentifier": "Guardrail ID",
        "guardrailVersion": "Guardrail version",
        "trace": "enabled"
}
```

`ConverseStream`을 사용하는 경우 [GuardrailStreamConfiguration](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_GuardrailStreamConfiguration.html) 객체를 전달합니다. 필요한 경우 `streamProcessingMode` 필드를 사용하여 스트리밍 응답 청크를 반환하기 전에 모델이 가드레일 평가를 완료하도록 지정할 수 있습니다. 또는 가드레일이 백그라운드에서 평가를 계속하는 동안 모델이 비동기식으로 응답하도록 할 수 있습니다. 자세한 내용은 [콘텐츠를 필터링하도록 스트리밍 응답 동작 구성](guardrails-streaming.md) 단원을 참조하십시오.

### 메시지의 특정 콘텐츠만 평가
<a name="guardrails-use-converse-api-call-message"></a>

[메시지](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Message.html)를 모델에 전달하면 가드레일이 메시지의 내용을 평가합니다. `guardContent`([GuardrailConverseContentBlock](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_GuardrailConverseContentBlock.html)) 필드를 사용하여 메시지의 특정 부분을 평가할 수도 있습니다.

**작은 정보**  
`guardContent` 필드를 사용하는 것은 [InvokeModel](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModel.html) 및 [InvokeModelWithResponseStream](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModelWithResponseStream.html)에 입력 태그를 사용하는 것과 유사합니다. 자세한 내용은 [사용자 입력에 태그를 적용하여 콘텐츠 필터링](guardrails-tagging.md) 단원을 참조하십시오.

예를 들어, 다음 가드레일은 `guardContent` 필드의 콘텐츠만 평가하며 메시지의 나머지 부분은 평가하지 않습니다. 이는 다음 예제와 같이 가드레일이 대화에서 최근 메시지만 평가하도록 하는 데 유용합니다.

```
[
    {
        "role": "user",
        "content": [
            {
                "text": "Create a playlist of 2 pop songs."
            }
        ]
    },
    {
        "role": "assistant",
        "content": [
            {
                "text": "Sure! Here are two pop songs:\n1. \"Bad Habits\" by Ed Sheeran\n2. \"All Of The Lights\" by Kanye West\n\nWould you like to add any more songs to this playlist?"
            }
        ]
    },
    {
        "role": "user",
        "content": [
            {
                "guardContent": {
                    "text": {
                        "text": "Create a playlist of 2 heavy metal songs."
                    }
                }
            }
        ]
    }
]
```

`guardContent`의 또 다른 사용 사례는 가드레일이 평가할 필요가 없는 추가 컨텍스트를 메시지에 제공하는 것입니다. 다음 예제에서 가드레일은 `"Create a playlist of heavy metal songs"`만 평가하고 `"Only answer with a list of songs"`는 무시합니다.

```
messages = [
    {
        "role": "user",
        "content": [
            {
                "text": "Only answer with a list of songs."
            },
            {
                "guardContent": {
                    "text": {
                        "text": "Create a playlist of heavy metal songs."
                    }
                }
            }
        ]
    }
]
```

콘텐츠가 `guardContent` 블록에 없는 경우 반드시 평가되지 않는다는 의미는 아닙니다. 이 동작은 가드레일이 사용하는 필터링 정책에 따라 달라집니다.

다음 예제는 [컨텍스트 근거 검사](guardrails-contextual-grounding-check.md)(`qualifiers` 필드 기반)가 있는 두 `guardContent` 블록을 보여줍니다. 가드레일의 컨텍스트 근거 검사는 이러한 블록의 콘텐츠만 평가합니다. 그러나 가드레일에 "background"라는 단어를 차단하는 [단어 필터](guardrails-content-filters.md)도 있는 경우 "Some additional background information"이라는 텍스트는 `guardContent` 블록에 없더라도 여전히 평가됩니다.

```
[{
    "role": "user",
    "content": [{
            "guardContent": {
                "text": {
                    "text": "London is the capital of UK. Tokyo is the capital of Japan.",
                    "qualifiers": ["grounding_source"]
                }
            }
        },
        {
            "text": "Some additional background information."
        },
        {
            "guardContent": {
                "text": {
                    "text": "What is the capital of Japan?",
                    "qualifiers": ["query"]
                }
            }
        }
    ]
}]
```

### Converse API로 전송된 시스템 프롬프트 보호
<a name="guardrails-use-converse-api-call-message-system-guard"></a>

Converse API로 전송하는 시스템 프롬프트와 함께 가드레일을 사용할 수 있습니다. 시스템 프롬프트를 보호하려면 다음 예제와 같이 API에 전달하는 시스템 프롬프트에서 `guardContent`([SystemContentBlock](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_SystemContentBlock.html)) 필드를 지정합니다.

```
[
    {
        "guardContent": {
            "text": {
                "text": "Only respond with Welsh heavy metal songs."
            }
        }
    }
]
```

`guardContent` 필드를 제공하지 않으면 가드레일은 시스템 프롬프트 메시지를 평가하지 않습니다.

### 메시지 및 시스템 프롬프트 가드레일 동작
<a name="guardrails-use-converse-api-call-message-system-message-guard"></a>

가드레일이 `guardContent` 필드를 평가하는 방법은 시스템 프롬프트와 사용자가 전달하는 메시지 사이에서 다르게 작동합니다.


|  | 시스템 프롬프트에 가드레일 블록이 있는 경우 | 시스템 프롬프트에 가드레일 블록이 없는 경우 | 
| --- | --- | --- | 
|  **메시지에 가드레일 블록이 있는 경우**  |  시스템: 가드레일이 가드레일 블록의 콘텐츠를 조사합니다. 메시지: 가드레일이 가드레일 블록의 콘텐츠를 조사합니다.  | 시스템: 가드레일이 아무것도 조사하지 않습니다. 메시지: 가드레일이 가드레일 블록의 콘텐츠를 조사합니다. | 
|  **메시지에 가드레일 블록이 있는 경우**  |  시스템: 가드레일이 가드레일 블록의 콘텐츠를 조사합니다. 메시지: 가드레일이 모든 것을 조사합니다.  |  시스템: 가드레일이 아무것도 조사하지 않습니다. 메시지: 가드레일이 모든 것을 조사합니다.  | 

## Converse API를 사용할 때 응답 처리
<a name="guardrails-use-converse-api-response"></a>

Converse 작업을 직접적으로 호출하면 가드레일은 사용자가 보내는 메시지를 평가합니다. 가드레일이 차단된 콘텐츠를 감지하면 다음과 같이 진행됩니다.
+ 응답의 `stopReason` 필드가 `guardrail_intervened`로 설정됩니다.
+ 추적을 활성화한 경우 `trace`([ConverseTrace](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ConverseTrace.html)) 필드에서 추적을 사용할 수 있습니다. `ConverseStream`을 사용하면 작업이 반환하는 메타데이터([ConverseStreamMetadataEvent](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ConverseStreamMetadataEvent.html))에 추적이 저장됩니다.
+ 가드레일에 구성한 차단된 콘텐츠 텍스트는 `output`([ConverseOutput](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ConverseOutput.html)) 필드에 반환됩니다. `ConverseStream`을 사용하면 차단된 콘텐츠 텍스트는 스트리밍된 메시지에 저장됩니다.

다음 부분 응답은 차단된 콘텐츠 텍스트와 가드레일 평가의 추적을 보여줍니다. 가드레일이 메시지에서 *Heavy metal*이라는 용어를 차단했습니다.

```
{
    "output": {
        "message": {
            "role": "assistant",
            "content": [
                {
                    "text": "Sorry, I can't answer questions about heavy metal music."
                }
            ]
        }
    },
    "stopReason": "guardrail_intervened",
    "usage": {
        "inputTokens": 0,
        "outputTokens": 0,
        "totalTokens": 0
    },
    "metrics": {
        "latencyMs": 721
    },
    "trace": {
        "guardrail": {
            "inputAssessment": {
                "3o06191495ze": {
                    "topicPolicy": {
                        "topics": [
                            {
                                "name": "Heavy metal",
                                "type": "DENY",
                                "action": "BLOCKED"
                            }
                        ]
                    },
                    "invocationMetrics": {
                        "guardrailProcessingLatency": 240,
                        "usage": {
                            "topicPolicyUnits": 1,
                            "contentPolicyUnits": 0,
                            "wordPolicyUnits": 0,
                            "sensitiveInformationPolicyUnits": 0,
                            "sensitiveInformationPolicyFreeUnits": 0,
                            "contextualGroundingPolicyUnits": 0
                        },
                        "guardrailCoverage": {
                            "textCharacters": {
                                "guarded": 39,
                                "total": 72
                            }
                        }
                    }
                }
            }
        }
    }
}
```

## 가드레일과 함께 Converse API를 사용하기 위한 예제 코드
<a name="converse-api-guardrail-example"></a>

이 예제에서는 `Converse` 및 `ConverseStream` 작업과의 대화를 보호하는 방법을 보여줍니다. 이 예제에서는 모델이 헤비 메탈 장르의 노래를 포함하는 재생 목록을 만들지 못하도록 하는 방법을 보여줍니다.

**대화를 보호하는 방법**

1. [가드레일 생성](guardrails-components.md)의 지침에 따라 가드레일을 만듭니다.
   + **이름** - *Heavy metal*을 입력합니다.
   + **주제에 대한 정의** - *Avoid mentioning songs that are from the heavy metal genre of music*(헤비 메탈 장르의 노래는 언급하지 마세요)이라고 입력합니다.
   + **샘플 문구 추가** - *Create a playlist of heavy metal songs*(헤비 메탈 노래 재생 목록을 만들어 주세요)라고 입력합니다.

   9단계에서 다음을 입력합니다.
   + **차단된 프롬프트에 표시되는 메시지** - *Sorry, I can't answer questions about heavy metal music*(헤비 메탈 음악에 대한 질문에는 답변을 드릴 수 없습니다)이라고 입력합니다.
   + **차단된 응답에 대한 메시지** - *Sorry, the model generated an answer that mentioned heavy metal music*(모델이 헤비 메탈 음악을 언급하는 답변을 생성했습니다)이라고 입력합니다.

   다른 가드레일 옵션도 구성할 수 있지만 이 예제에서는 필요하지 않습니다.

1. [가드레일 버전 생성](guardrails-versions-create.md)의 지침에 따라 가드레일 버전을 만듭니다.

1. 다음 코드 예제([Converse](#converse-api-guardrail-example-converse) 및 [ConverseStream](#converse-api-guardrail-example-converse-stream))에서 다음 변수를 설정합니다.
   + `guardrail_id` - 1단계에서 만든 가드레일의 ID입니다.
   + `guardrail_version` - 2단계에서 만든 가드레일의 버전입니다.
   + `text` – `Create a playlist of heavy metal songs.`를 사용합니다.

1. 예제 코드를 실행합니다. 출력에는 가드레일 평가와 출력 메시지(`Text: Sorry, I can't answer questions about heavy metal music.`)가 표시되어야 합니다. 가드레일 입력 평가는 모델이 입력 메시지에서 *heavy metal*이라는 용어를 감지했음을 보여줍니다.

1. (선택 사항) `text`의 값을 *List all genres of rock music*(락 음악의 모든 장르를 나열해 주세요)으로 변경하여 가드레일이 모델이 생성하는 부적절한 텍스트를 차단하는지 테스트합니다. 예제를 다시 실행합니다. 응답에 출력 평가가 표시됩니다.

------
#### [ Converse ]

다음 코드는 `Converse` 작업에 가드레일을 사용합니다.

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""
Shows how to use a guardrail with the <noloc>Converse</noloc> API.
"""

import logging
import json
import boto3


from botocore.exceptions import ClientError


logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)


def generate_conversation(bedrock_client,
                          model_id,
                          messages,
                          guardrail_config):
    """
    Sends a message to a model.
    Args:
        bedrock_client: The Boto3 Bedrock runtime client.
        model_id (str): The model ID to use.
        messages JSON): The message to send to the model.
        guardrail_config : Configuration for the guardrail.

    Returns:
        response (JSON): The conversation that the model generated.

    """

    logger.info("Generating message with model %s", model_id)

    # Send the message.
    response = bedrock_client.converse(
        modelId=model_id,
        messages=messages,
        guardrailConfig=guardrail_config
    )

    return response


def main():
    """
    Entrypoint for example.
    """

    logging.basicConfig(level=logging.INFO,
                        format="%(levelname)s: %(message)s")

    # The model to use.
    model_id="meta.llama3-8b-instruct-v1:0"

    # The ID and version of the guardrail.
    guardrail_id = "Your guardrail ID"
    guardrail_version = "DRAFT"

    # Configuration for the guardrail.
    guardrail_config = {
        "guardrailIdentifier": guardrail_id,
        "guardrailVersion": guardrail_version,
        "trace": "enabled"
    }

    text = "Create a playlist of 2 heavy metal songs."
    context_text = "Only answer with a list of songs."

    # The message for the model and the content that you want the guardrail to assess.
    messages = [
        {
            "role": "user",
            "content": [
                {
                    "text": context_text,
                },
                {
                    "guardContent": {
                        "text": {
                            "text": text
                        }
                    }
                }
            ]
        }
    ]

    try:

        print(json.dumps(messages, indent=4))

        bedrock_client = boto3.client(service_name='bedrock-runtime')

        response = generate_conversation(
            bedrock_client, model_id, messages, guardrail_config)

        output_message = response['output']['message']

        if response['stopReason'] == "guardrail_intervened":
            trace = response['trace']
            print("Guardrail trace:")
            print(json.dumps(trace['guardrail'], indent=4))

        for content in output_message['content']:
            print(f"Text: {content['text']}")

    except ClientError as err:
        message = err.response['Error']['Message']
        logger.error("A client error occurred: %s", message)
        print(f"A client error occured: {message}")

    else:
        print(
            f"Finished generating text with model {model_id}.")


if __name__ == "__main__":
    main()
```

------
#### [ ConverseStream ]

다음 코드는 `ConverseStream` 작업에 가드레일을 사용합니다.

```
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""
Shows how to use a guardrail with the ConverseStream operation.
"""

import logging
import json
import boto3


from botocore.exceptions import ClientError


logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)


def stream_conversation(bedrock_client,
                    model_id,
                    messages,
                    guardrail_config):
    """
    Sends messages to a model and streams the response.
    Args:
        bedrock_client: The Boto3 Bedrock runtime client.
        model_id (str): The model ID to use.
        messages (JSON) : The messages to send.
        guardrail_config : Configuration for the guardrail.


    Returns:
        Nothing.

    """

    logger.info("Streaming messages with model %s", model_id)

    response = bedrock_client.converse_stream(
        modelId=model_id,
        messages=messages,
        guardrailConfig=guardrail_config
    )

    stream = response.get('stream')
    if stream:
        for event in stream:

            if 'messageStart' in event:
                print(f"\nRole: {event['messageStart']['role']}")

            if 'contentBlockDelta' in event:
                print(event['contentBlockDelta']['delta']['text'], end="")

            if 'messageStop' in event:
                print(f"\nStop reason: {event['messageStop']['stopReason']}")

            if 'metadata' in event:
                metadata = event['metadata']
                if 'trace' in metadata:
                    print("\nAssessment")
                    print(json.dumps(metadata['trace'], indent=4))


def main():
    """
    Entrypoint for streaming message API response example.
    """

    logging.basicConfig(level=logging.INFO,
                        format="%(levelname)s: %(message)s")

    # The model to use.
    model_id = "amazon.titan-text-express-v1"

    # The ID and version of the guardrail.
    guardrail_id = "Change to your guardrail ID"
    guardrail_version = "DRAFT"

    # Configuration for the guardrail.
    guardrail_config = {
        "guardrailIdentifier": guardrail_id,
        "guardrailVersion": guardrail_version,
        "trace": "enabled",
        "streamProcessingMode" : "sync"
    }

    text = "Create a playlist of heavy metal songs."
  
    # The message for the model and the content that you want the guardrail to assess.
    messages = [
        {
            "role": "user",
            "content": [
                {
                    "text": text,
                },
                {
                    "guardContent": {
                        "text": {
                            "text": text
                        }
                    }
                }
            ]
        }
    ]

    try:
        bedrock_client = boto3.client(service_name='bedrock-runtime')

        stream_conversation(bedrock_client, model_id, messages,
                        guardrail_config)

    except ClientError as err:
        message = err.response['Error']['Message']
        logger.error("A client error occurred: %s", message)
        print("A client error occured: " +
              format(message))

    else:
        print(
            f"Finished streaming messages with model {model_id}.")


if __name__ == "__main__":
    main()
```

------