

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

# Amazon Bedrock 흐름을 사용한 대화
<a name="flows-multi-turn-invocation"></a>

**참고**  
Amazon Bedrock Flows 멀티턴 대화는 Amazon Bedrock 평가판 릴리스이며 변경될 수 있습니다.

Amazon Bedrock Flows 멀티턴 대화는 자연스러운 대화와 마찬가지로 사용자와 흐름 간 주고 받는 동적인 대화를 가능하게 합니다. 에이전트 노드에 설명 또는 추가 컨텍스트가 필요한 경우 흐름 실행을 지능적으로 일시 중지하고 사용자에게 특정 정보를 묻는 메시지를 표시할 수 있습니다. 이렇게 하면 노드가 사용자 응답에 따라 동작을 조정할 수 있으므로 더 강력한 대화형 컨텍스트 인식 경험이 제공됩니다. 예를 들어 초기 사용자 쿼리가 모호하거나 불완전한 경우 노드는 후속 질문을 통해 필요한 세부 정보를 수집할 수 있습니다. 사용자가 요청된 정보를 제공하면 흐름은 보강된 입력으로 실행을 원활하게 재개하여 더 정확하고 관련성이 높은 결과를 보장합니다. 이 기능은 단일 상호 작용만으로는 사용자의 요구 사항을 완전히 이해하고 해결하는 데 충분하지 않을 수 있는 복잡한 상황에 특히 유용합니다.

**Topics**
+ [흐름에서 멀티턴 대화를 처리하는 방법](#flows-multi-turn-invocation-how)
+ [예제 흐름 생성 및 실행](#flows-multi-turn-invocation-example-flow)

## 흐름에서 멀티턴 대화를 처리하는 방법
<a name="flows-multi-turn-invocation-how"></a>

흐름에서 멀티턴 대화를 사용하려면 Amazon Bedrock 에이전트에 연결된 [에이전트 노드](flows-nodes.md#flows-nodes-agent)가 필요합니다. 흐름을 실행하면 에이전트가 사용자로부터 추가 정보를 받아야 진행할 수 있을 때 멀티턴 대화가 발생합니다. 이 섹션에서는 다음 지침에 따라 에이전트를 사용하는 흐름에 대해 설명합니다.

```
You are a playlist creator for a radio station. 
When asked to create a playlist, ask for the number of songs,
the genre of music, and a theme for the playlist.
```

에이전트 생성에 대한 자세한 내용은 [AI 에이전트를 사용하여 애플리케이션에서 태스크 자동화](agents.md) 섹션을 참조하세요.

### 1단계: 흐름 시작
<a name="flows-multi-turn-invocation-start-flow"></a>

[InvokeFlow](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent-runtime_InvokeFlow.html) 작업을 직접 호출하여 흐름을 시작합니다. 흐름에 보내려는 초기 콘텐츠를 포함합니다. 다음 예제에서 `document` 필드에는 *재생 목록 생성*에 대한 요청이 포함되어 있습니다. 각 대화에는 흐름 내에서 대화를 식별하는 고유한 식별자(*실행 ID*)가 있습니다. 실행 ID를 가져오려면 첫 번째 직접 호출의 `executionID` 필드를 `InvokeFlow`로 보내지 않습니다. `InvokeFlow`의 응답에는 실행 ID가 포함됩니다. 코드에서 식별자를 사용하여 여러 대화를 추적하고 `InvokeFlow` 작업에 대한 추가적인 직접 호출에서 대화를 식별합니다.

다음은 `InvokeFlow` 요청에 대한 JSON 예제입니다.

```
{
  "flowIdentifier": "XXXXXXXXXX",
  "flowAliasIdentifier": "YYYYYYYYYY",
  "inputs": [
    {
      "content": {
        "document": "Create a playlist."
      },
      "nodeName": "FlowInputNode",
      "nodeOutputName": "document"
    }
  ]
}
```

### 2단계: 에이전트 요청 가져오기
<a name="flows-multi-turn-invocation-retrieve-requests"></a>

흐름에서 에이전트 노드가 사용자의 추가 정보가 필요하다고 판단하면 `InvokeFlow`의 응답 스트림(`responseStream`)에 `FlowMultiTurnInputRequestEvent` 이벤트 객체가 포함됩니다. 요청된 정보는 이벤트의 `content`(`FlowMultiTurnInputContent`) 필드에 있습니다. 다음 예제에서 `document` 필드의 요청은 노래 수, 음악 장르 및 재생 목록 테마 관련 정보에 대한 것입니다. 코드에서 사용자로부터 해당 정보를 가져와야 합니다.

다음은 `FlowMultiTurnInputRequestEvent` JSON 객체의 예입니다.

```
{
    "nodeName": "AgentsNode_1",
    "nodeType": "AgentNode",
    "content": {
        "document": "Certainly! I'd be happy to create a playlist for you. To make sure it's tailored to your preferences, could you please provide me with the following information:
        1. How many songs would you like in the playlist?
        2. What genre of music do you prefer? 
        3. Is there a specific theme or mood you'd like for the playlist? Once you provide these details, I'll be able to create a customized playlist just for you."
    }
}
```

흐름은 더 많은 입력이 수신되어야 진행 가능하므로 `FlowCompletionEvent` 이벤트도 내보냅니다. 흐름은 항상 `FlowCompletionEvent` 앞에 `FlowMultiTurnInputRequestEvent`를 내보냅니다. `FlowCompletionEvent` 이벤트 내 `completionReason`의 값이 `INPUT_REQUIRED`인 경우 흐름은 계속하기 전에 추가 정보가 필요합니다.

다음은 `FlowCompletionEvent` JSON 객체의 예입니다.

```
{
    "completionReason": "INPUT_REQUIRED"
}
```

### 3단계: 흐름에 사용자 응답 전송
<a name="flows-multi-turn-invocation-continue"></a>

`InvokeFlow` 작업을 다시 직접적으로 호출하여 사용자 응답을 흐름으로 다시 보냅니다. 대화에 `executionId`를 포함해야 합니다.

다음은 `InvokeFlow` 요청에 대한 JSON의 예입니다. 이 `document` 필드에는 사용자의 응답이 포함됩니다.

```
{
  "flowIdentifier": "AUS7BMHXBE",
  "flowAliasIdentifier": "4KUDB8VBEF",
  "executionId": "b6450554-f8cc-4934-bf46-f66ed89b60a0",
  "inputs": [
    {
      "content": {
        "document": "1. 5 songs 2. Welsh rock music 3. Castles"
      },
      "nodeName": "AgentsNode_1",
      "nodeInputName": "agentInputText"
    }
  ]
}
```

흐름에 추가 정보가 필요한 경우 흐름은 추가 `FlowMultiTurnInputRequestEvent` 이벤트를 생성합니다.

### 4단계: 흐름 종료
<a name="flows-multi-turn-invocation-end"></a>

추가 정보가 더 이상 필요하지 않으면 흐름은 최종 응답이 포함된 `FlowOutputEvent` 이벤트를 내보냅니다.

다음은 `FlowOutputEvent` JSON 객체의 예입니다.

```
{
    "nodeName": "FlowOutputNode",
    "content": {
        "document": "Great news! I've created a 5-song Welsh rock playlist centered around the theme of castles. 
        Here's the playlist I've put together for you: Playlist Name: Welsh Rock Castle Anthems 
        Description: A 5-song Welsh rock playlist featuring songs about castles 
        Songs: 
        1. Castell y Bere - Super Furry Animals 
        2. The Castle - Manic Street Preachers 
        3. Caerdydd (Cardiff Castle) - Stereophonics 
        4. Castell Coch - Catatonia 
        5. Chepstow Castle - Feeder 
        This playlist combines Welsh rock bands with songs that reference castles or specific Welsh castles. 
        Enjoy your castle-themed Welsh rock music experience!"
     }
}
```

흐름은 `FlowCompletionEvent` 이벤트도 내보냅니다. `completionReason`의 값이 `SUCCESS`입니다.

다음은 `FlowCompletionEvent` JSON 객체의 예입니다.

```
{
    "completionReason": "SUCCESS"
}
```

다음 시퀀스 다이어그램은 멀티턴 흐름의 단계를 보여줍니다.

![\[멀티턴 대화의 흐름 단계입니다.\]](http://docs.aws.amazon.com/ko_kr/bedrock/latest/userguide/images/flows/flows-multi-turn-steps.png)


## 예제 흐름 생성 및 실행
<a name="flows-multi-turn-invocation-example-flow"></a>

이 예제에서는 에이전트를 사용하여 라디오 방송국의 재생 목록을 만드는 흐름을 생성합니다. 에이전트는 노래 수, 음악 장르, 재생 목록 테마를 확인하기 위해 명확한 질문을 합니다.

**흐름을 만드는 방법**

1. [에이전트를 수동으로 생성 및 구성](agents-create.md)의 지침에 따라 Amazon Bedrock 콘솔에서 에이전트를 생성합니다.
   + *2.d*단계에서 **You are a playlist creator for a radio station. When asked to create a playlist, ask for the number of songs, the genre of music, and a theme for the playlist.**를 입력합니다.
   + *2.e*단계의 **사용자 입력**에서 **활성화됨**을 선택합니다. 이렇게 하면 에이전트가 필요에 따라 추가 정보를 요청할 수 있습니다.

1. [Amazon Bedrock에서 흐름 생성 및 설계](flows-create.md)의 지침에 따라 흐름을 생성합니다. 흐름에 입력 노드, 에이전트 노드 및 출력 노드가 있는지 확인합니다.

1. 에이전트 노드를 1단계에서 생성된 에이전트에 연결합니다. 흐름은 다음 이미지와 같게 됩니다.  
![\[멀티턴 대화 흐름\]](http://docs.aws.amazon.com/ko_kr/bedrock/latest/userguide/images/flows/flows-multi-turn.png)

1. Amazon Bedrock 콘솔에서 흐름을 실행합니다. 테스트를 위해 흐름이 수행하는 단계를 추적할 수 있습니다. 자세한 내용은 [Amazon Bedrock에서 흐름 테스트](flows-test.md) 단원을 참조하십시오.

다음 Python 코드 예제는 흐름을 사용하는 방법을 보여줍니다.

코드를 실행하려면 다음을 지정합니다.
+ `region_name` - 흐름을 실행 중인 AWS 리전입니다.
+ `FLOW_ID` - 흐름의 ID.
+ `FLOW_ALIAS_ID` - 흐름의 별칭 ID.

이 ID를 가져오는 방법에 대한 내용은 [Amazon Bedrock에서 흐름 정보 확인](flows-view.md) 섹션을 참조하세요. 코드는 흐름에 전송하기 위한 초기 요청을 메시지로 표시하고 흐름에 필요한 만큼 더 많은 입력을 요청합니다. 코드는 AWS Lambda 함수 호출 요청과 같은 에이전트의 다른 요청을 관리하지 않습니다. 자세한 내용은 [Amazon Bedrock Agents의 작동 방식](agents-how.md) 단원을 참조하십시오. 실행 중에 코드는 입력에서 흐름이 반환하는 응답까지의 경로를 추적하는 데 사용할 수 있는 `FlowTraceEvent` 객체를 생성합니다. 자세한 내용은 [Amazon Bedrock에서 추적을 확인하여 흐름의 각 단계 추적추적을 확인하여 흐름의 각 단계 추적](flows-trace.md) 단원을 참조하십시오.

```
"""
Runs an Amazon Bedrock flow and handles muli-turn interaction for a single conversation.

"""
import logging
import boto3
import botocore



import botocore.exceptions

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


def invoke_flow(client, flow_id, flow_alias_id, input_data, execution_id):
    """
    Invoke an Amazon Bedrock flow and handle the response stream.

    Args:
        client: Boto3 client for Amazon Bedrock agent runtime
        flow_id: The ID of the flow to invoke
        flow_alias_id: The alias ID of the flow
        input_data: Input data for the flow
        execution_id: Execution ID for continuing a flow. Use the value None on first run.

    Returns:
        Dict containing flow_complete status, input_required info, and execution_id
    """

    response = None
    request_params = None

    if execution_id is None:
        # Don't pass execution ID for first run.
        request_params = {
            "flowIdentifier": flow_id,
            "flowAliasIdentifier": flow_alias_id,
            "inputs": [input_data],
            "enableTrace": True
        }
    else:
        request_params = {
            "flowIdentifier": flow_id,
            "flowAliasIdentifier": flow_alias_id,
            "executionId": execution_id,
            "inputs": [input_data],
            "enableTrace": True
        }

    response = client.invoke_flow(**request_params)
    if "executionId" not in request_params:
        execution_id = response['executionId']

    input_required = None
    flow_status = ""

    # Process the streaming response
    for event in response['responseStream']:
        # Check if flow is complete.
        if 'flowCompletionEvent' in event:
            flow_status = event['flowCompletionEvent']['completionReason']

        # Check if more input us needed from user.
        elif 'flowMultiTurnInputRequestEvent' in event:
            input_required = event

        # Print the model output.
        elif 'flowOutputEvent' in event:
            print(event['flowOutputEvent']['content']['document'])

        elif 'flowTraceEvent' in event:
            logger.info("Flow trace:  %s", event['flowTraceEvent'])

    return {
        "flow_status": flow_status,
        "input_required": input_required,
        "execution_id": execution_id
    }


if __name__ == "__main__":

    session = boto3.Session(profile_name='default', region_name='YOUR_FLOW_REGION')
    bedrock_agent_client = session.client('bedrock-agent-runtime')
    
    # Replace these with your actual flow ID and alias ID
    FLOW_ID = 'YOUR_FLOW_ID'
    FLOW_ALIAS_ID = 'YOUR_FLOW_ALIAS_ID'


    flow_execution_id = None
    finished = False

    # Get the intial prompt from the user.
    user_input = input("Enter input: ")

    flow_input_data = {
        "content": {
            "document": user_input
        },
        "nodeName": "FlowInputNode",
        "nodeOutputName": "document"
    }

    logger.info("Starting flow %s", FLOW_ID)

    try:
        while not finished:
            # Invoke the flow until successfully finished.

            result = invoke_flow(
                bedrock_agent_client, FLOW_ID, FLOW_ALIAS_ID, flow_input_data, flow_execution_id)
            status = result['flow_status']
            flow_execution_id = result['execution_id']
            more_input = result['input_required']
            if status == "INPUT_REQUIRED":
                # The flow needs more information from the user.
                logger.info("The flow %s requires more input", FLOW_ID)
                user_input = input(
                    more_input['flowMultiTurnInputRequestEvent']['content']['document'] + ": ")
                flow_input_data = {
                    "content": {
                        "document": user_input
                    },
                    "nodeName": more_input['flowMultiTurnInputRequestEvent']['nodeName'],
                    "nodeInputName": "agentInputText"

                }
            elif status == "SUCCESS":
                # The flow completed successfully.
                finished = True
                logger.info("The flow %s successfully completed.", FLOW_ID)

    except botocore.exceptions.ClientError as e:
        print(f"Client error: {str(e)}")
        logger.error("Client error: %s", {str(e)})

    except Exception as e:
        print(f"An error occurred: {str(e)}")
        logger.error("An error occurred: %s", {str(e)})
        logger.error("Error type: %s", {type(e)})
```