Skip to content

Latest commit

 

History

History
330 lines (232 loc) · 14.1 KB

prompt-flow.md

File metadata and controls

330 lines (232 loc) · 14.1 KB

Prompt Flow 활용하기

Prompt Flow를 이용하면 prompt flow builder를 이용하여 손쉽게 chatbot을 만들 수 있습니다. 여기에서는 Anthropic의 Claude Sonnet를 이용하여 아래와 같은 chatbot을 구현하고, 애플리케이션에서 활용하는 방법을 설명합니다.

  1. 이름을 가진 chatbot 구현하기: "AWS"라는 이름을 가지는 chatbot을 구현하여 prompt flow의 동작을 이해합니다.
  2. RAG를 활용하는 Chatbot 구현하기: No code로 RAG를 구현하기 위하여 Knowledge Base를 활용합니다.

Prompt Flow로 이름을 가지는 Chatbot 구현하기

Prompt flow를 이용하면 별도 코딩없이 Prompt, RAG, Lambda등을 chatbot에 통합할 수 있습니다. 여기에서는 prompt flow의 동작 방식을 설명하기 위하여, "AWS"라는 이름을 가지는 간단한 chatbot을 구현하는 것을 설명합니다.

  1. Prompt flow console에 접속하여 [Create prompt flow] 선택하고 아래와 같이 입력 후에 [Create]를 선택합니다. 여기서 prompt flow의 이름을 "aws-bot"으로 입력합니다.
image
  1. 왼쪽의 [Nodes]에서 [Prompts[를 선택하여 아래와 같이 드래그인합니다. 이후 [Define in node]을 선택하고, Model은 "Claude 3 Sonnet"을 지정하였으며, Prompt에는 "너의 이름은 AWS이고 질문에 답변을 하는 AI Assistant입니다. 다음의 {{input}}에 대해 구체적인 세부 정보를 충분히 제공합니다."라고 입력합니다.

noname

  1. 아래와 같이 "Flow input", "Flow output" 노드와 연결해 주고, [Save] 버튼을 선택하여 작업한 내용을 저장합니다.
image
  1. 오른쪽의 [Test Prompt flow]의 입력창에 "안녕"이라고 입력하면, 아래와 같이 "AWS"라는 이름을 가지는 chatbot이 생성되었음을 알 수 있습니다.

image

  1. 다시 Prompt flow console에서 생성한 "aws-bot"을 선택한 후에 아래와 같이 [Publish version]을 선택하면 "Version 1"이 생성됩니다.
image
  1. 아래로 스크롤하여 [Create alias]를 선택합니다.
image

이후 아래와 같이 "Alias name"으로 "latest_version"라고 입력한 후에 [Create Alias]를 선택합니다.

image

애플리케이션에서 Prompt Flow 활용하기

프롬프트 플로우 실행 코드 샘플를 참조하여 구현합니다. 상세한 코드는 lambda_function.py을 참조합니다.

각종 Parameter

POST /flows/flowIdentifier/aliases/flowAliasIdentifier HTTP/1.1
Content-type: application/json

{
   "inputs": [ 
      { 
         "content": { ... },
         "nodeName": "string",
         "nodeOutputName": "string"
      }
   ]
}

여기서, JSON에 필요한 값들은 아래와 같습니다.

  • nodeName: flow input node의 이름

  • nodeOutputName: prompt flow의 시작인 input node의 output의 이름

현재 작성한 prompt flow는 nodeName이 "FlowInputNode"이고, nodeOutputName은 "document"입니다.

애플리케이션에서 Prompt Flow를 이용하여 Chatbot 활용하기

아래와 같이 flow_id로 "Prompt flow ARN"을 붙여넣기하고, flow_alias는 생성할 때에 사용한 "aws"을 입력합니다. "flowAliasIdentifier"는 아래와 같이 list_flow_aliases()에서 alias를 검색하여 확인합니다. invoke_flow()을 이용하여 prompt flow에 입력문을 전달후 결과를 얻습니다.

flow_arn = None
flow_alias_identifier = None
def run_prompt_flow(text, connectionId, requestId):    
    client = boto3.client(service_name='bedrock-agent')   
    
    global flow_arn, flow_alias_identifier    
    if not flow_arn:
        response = client.list_flows(
            maxResults=10
        )
        print('response: ', response)
        
        for flow in response["flowSummaries"]:
            print('flow: ', flow)
            if flow["name"] == prompt_flow_name:
                flow_arn = flow["arn"]
                print('flow_arn: ', flow_arn)
                break

    msg = ""
    if flow_arn:
        if not flow_alias_identifier:
            # get flow alias arn
            response_flow_aliases = client.list_flow_aliases(
                flowIdentifier=flow_arn
            )
            print('response_flow_aliases: ', response_flow_aliases)
            
            flowAlias = response_flow_aliases["flowAliasSummaries"]
            for alias in flowAlias:
                print('alias: ', alias)
                if alias['name'] == "latest_version":  # the name of prompt flow alias
                    flow_alias_identifier = alias['arn']
                    print('flowAliasIdentifier: ', flow_alias_identifier)
                    break
        
        # invoke_flow
        isTyping(connectionId, requestId)  
        
        client_runtime = boto3.client('bedrock-agent-runtime')
        response = client_runtime.invoke_flow(
            flowIdentifier=flow_arn,
            flowAliasIdentifier=flow_alias_identifier,
            inputs=[
                {
                    "content": {
                        "document": text,
                    },
                    "nodeName": "FlowInputNode",
                    "nodeOutputName": "document"
                }
            ]
        )
        print('response of invoke_flow(): ', response)
        
        response_stream = response['responseStream']
        try:
            result = {}
            for event in response_stream:
                print('event: ', event)
                result.update(event)
            print('result: ', result)

            if result['flowCompletionEvent']['completionReason'] == 'SUCCESS':
                print("Prompt flow invocation was successful! The output of the prompt flow is as follows:\n")
                # msg = result['flowOutputEvent']['content']['document']
                
                msg = readStreamMsg(connectionId, requestId, result['flowOutputEvent']['content']['document'])
                print('msg: ', msg)
            else:
                print("The prompt flow invocation completed because of the following reason:", result['flowCompletionEvent']['completionReason'])
        except Exception as e:
            raise Exception("unexpected event.",e)

    return msg

실행결과

애플리케이션을 실행하고 메뉴에서 "Prompt Flow"을 선택한 후에 아래와 같이 "안녕"이라고 입력하고 결과를 확인합니다. Prompt flow를 이용하여 "AWS"라는 이름의 chatbot을 생성할 수 있었습니다.

image

RAG를 활용하는 Chatbot 구현하기

Knowdge Base로 RAG 구현

Prompt flow의 Knowledge Base 노드에서는 두 가지 옵션을 제공합니다.

  • Generate responses based on retrieved results: Knowledge Base에 질문을 하면, 기본 Prompt를 이용하여 문자열(string)으로 된 답변을 제공하여 편리하게 활용할 수 있습니다.

  • Return retrieved results: Knowledge Base에 질문을 하면, 조회된 관련된 문서를 array로 전달합니다. 여기에는 문서뿐 아니라 context, 관련문서(reference)의 URI를 제공합니다.

knowledge-base.md와 같이 "aws-rag"라는 이름을 가지는 Knowledge Base를 이용한 Knowledge store를 구현합니다.

Prompt Flow를 이용해 No Code로 RAG 활용하기

  1. Prompt Flow Console에서 [Create prompt flow]를 선택한 후에 아래와 같이 이름을 지정합니다. 여기에서는 "rag-prompt-flow"로 지정하였습니다.
image
  1. 생성된 Prompt Flow에 선택한 후에 [Edit in prompt flow builder]을 선택합니다.

  2. Node에서 "Knowledge Base"를 드레그인 하여 아래와 같이 배치합니다.

image
  1. Knowledge Base를 아래와 같이 설정합니다.
image
  1. RAG 동작을 아래와 같이 확인할 수 있습니다.
image

애플리케이션에서 RAG 활용하기

애플리케이션을 실행하고 메뉴에서 "Prompt Flow (RAG)"을 선택한 후에, 아래와 같이 "Amazon bedrock agent에 대해 설명해줘"라고 입력합니다.

image

client에서는 boto3의 invoke_flow을 이용해 RAG가 포함된 prompt flow결과를 얻어옵니다.

rag_flow_arn = None
rag_flow_alias_identifier = None
def run_RAG_prompt_flow(text, connectionId, requestId):
    global rag_flow_arn, rag_flow_alias_identifier
    
    client = boto3.client(service_name='bedrock-agent')       
    if not rag_flow_arn:
        response = client.list_flows(
            maxResults=10
        )
         
        for flow in response["flowSummaries"]:
            if flow["name"] == rag_prompt_flow_name:
                rag_flow_arn = flow["arn"]
                break
    
    if not rag_flow_alias_identifier and rag_flow_arn:
        # get flow alias arn
        response_flow_aliases = client.list_flow_aliases(
            flowIdentifier=rag_flow_arn
        )
        rag_flow_alias_identifier = ""
        flowAlias = response_flow_aliases["flowAliasSummaries"]
        for alias in flowAlias:
            if alias['name'] == "latest_version":  # the name of prompt flow alias
                rag_flow_alias_identifier = alias['arn']
                break
    
    # invoke_flow
    isTyping(connectionId, requestId)  
    
    client_runtime = boto3.client('bedrock-agent-runtime')
    response = client_runtime.invoke_flow(
        flowIdentifier=rag_flow_arn,
        flowAliasIdentifier=rag_flow_alias_identifier,
        inputs=[
            {
                "content": {
                    "document": text,
                },
                "nodeName": "FlowInputNode",
                "nodeOutputName": "document"
            }
        ]
    )
    
    response_stream = response['responseStream']
    try:
        result = {}
        for event in response_stream:
            result.update(event)

        if result['flowCompletionEvent']['completionReason'] == 'SUCCESS':            
            msg = readStreamMsg(connectionId, requestId, result['flowOutputEvent']['content']['document'])

    except Exception as e:
        raise Exception("unexpected event.",e)

    return msg

RAG에서 Prompt 사용하기

Prompt flow에서 Knowledge base를 이용할때에 "Generate responses based on retrieved results"을 사용하면 미리 지정된 Prompt를 활용하여 문자열로 된 결과를 얻을 수 있어서 편리합니다. 하지만, 챗봇의 이름등 프롬프트를 수정하여 사용할 경우에는 "Return retrieved results"을 사용하여 관련된 문서를 얻고, 아래와 같이 Prompt를 추가하여 활용할 수 있습니다.

image

이때 사용한 prompt는 아래와 같습니다.

너의 이름은 "AWS"입니다. 다음의 <context> tag안의 참고자료를 이용하여 상황에 맞는 구체적인 세부 정보를 충분히 제공합니다. 모르는 질문을 받으면 솔직히 모른다고 말합니다.

<context>
{{context}}
</context>

<question>
{{input}}
</question>

이때의 결과는 아래와 같습니다.

image