API를 사용하여 사용자 정의 클라이언트 빌드

자동 학습 기능 watsonx Assistant
2025년 6월 16일부터 watsonx Assistant 에 대한 자동 학습 기능이 중단됩니다. 이 날짜 이후에는 자동 학습 설정이 작업 글로벌 설정 페이지에서 제거되고 모든 자동 학습 기능이 비활성화됩니다.

기본 제공 통합 기능 중 요구 사항을 충족하는 것이 없는 경우에는 사용자와 상호 작용하고 IBM® watsonx™ Assistant 서비스와 통신하는 사용자 지정 클라이언트 애플리케이션을 개발하여 어시스턴트를 배포할 수 있습니다.

Watson SDK를 사용하여 watsonx Assistant와 상호작용하는 코드를 작성할 수 있습니다. SDK에 대한 자세한 내용은 IBM Watson API를 참조하세요.

어시스턴트 설정

여기서 작성하는 예제 애플리케이션은 클라이언트 애플리케이션이 watsonx Assistant와 상호작용하는 방법을 설명하는 몇 가지 단순 함수를 구현합니다. 애플리케이션 코드는 입력을 수집하고 이를 어시스턴트에 전송하며, 어시스턴트는 애플리케이션이 사용자에게 표시하는 응답을 전송합니다.

이 예제를 직접 시도하려면 먼저 클라이언트가 연결하는 단순 예제 지원을 설정해야 합니다.

  1. 조치 JSON 파일을 다운로드하십시오.
  2. 어시스턴트를 작성하십시오.
  3. 새 어시스턴트에서 글로벌 조치 설정을 여십시오. 업로드/다운로드 탭으로 이동하여 다운로드한 파일에서 조치를 가져오십시오.

예제 조치에는 고객의 이름을 묻는 Greet customer 조치와 약속일정 작성 및 취소를 위한 단순 조치가 포함되어 있습니다.

서비스 정보 가져오기

watsonx Assistant REST API에 액세스하려면 애플리케이션이 IBM Cloud® 로 인증하고 애플리케이션이 배치되는 환경에서 어시스턴트에 연결할 수 있어야 합니다. 서비스 자격 증명과 환경 ID를 복사하여 애플리케이션 코드에 붙여넣어야 합니다. 또한 서비스 인스턴스의 위치를 나타내는 URL (예: https://api.us-south.assistant.watson.cloud.ibm.com)도 필요합니다.

이 정보를 찾으려면 다음을 수행하십시오.

  1. 환경 페이지로 이동하여 연결할 환경을 선택하십시오.

  2. 설정 아이콘 톱니바퀴 아이콘을 클릭하여 환경 설정을 엽니다.

  3. API 세부 정보를 선택하면 서비스 인스턴스 URL 및 환경 ID를 포함한 환경의 세부 정보를 볼 수 있습니다. API키를 찾으려면 서비스 인증 정보 섹션의 링크를 따르십시오.

watsonx Assistant 서비스와 통신하기

클라이언트 애플리케이션에서 watsonx Assistant 서비스와 상호작용하는 것은 간단합니다. 서비스에 연결하여 빈 메시지 하나를 전송하고 콘솔에 출력을 인쇄하는 예제부터 시작합니다:

// Example 1: Creates service object, sends initial message, and
// receives response.

const AssistantV2 = require('ibm-watson/assistant/v2');
const { IamAuthenticator } = require('ibm-watson/auth');

// Create Assistant service object.
const assistant = new AssistantV2({
  version: '2021-11-27',
  authenticator: new IamAuthenticator({
    apikey: '{apikey}', // replace with API key
  }),
  url: '{url}', // replace with URL
});

const assistantId = '{environment_id}'; // replace with environment ID

// Start conversation with empty message
messageInput = {
  messageType: 'text',
  text: '',
};
sendMessage(messageInput);

// Send message to assistant.
function sendMessage(messageInput) {
  assistant
    .messageStateless({
      assistantId,
      input: messageInput,
    })
    .then(res => {
      processResult(res.result);
    })
    .catch(err => {
      console.log(err); // something went wrong
    });
}

// Process the result.
function processResult(result) {
  // Print responses from actions, if any. Supports only text responses.
  if (result.output.generic) {
    if (result.output.generic.length > 0) {
      result.output.generic.forEach( response => {
        if (response.response_type == 'text') {
          console.log(response.text);
        }
      });
    }
  }
}
# Example 1: Creates service object, sends initial message, and
# receives response.

from ibm_watson import AssistantV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

# Create Assistant service object.
authenticator = IAMAuthenticator('{apikey}') # replace with API key
assistant = AssistantV2(
    version = '2021-11-27',
    authenticator = authenticator
)
assistant.set_service_url('{url}') # replace with service instance URL
assistant_id = '{environment_id}' # replace with environment ID

# Start conversation with empty message.
result = assistant.message_stateless(
    assistant_id,
).get_result()

# Print responses from actions, if any. Supports only text responses.
if result['output']['generic']:
    for response in result['output']['generic']:
        if response['response_type'] == 'text':
            print(response['text'])

첫 번째 단계는 watsonx Assistant 서비스에 대한 일종의 래퍼인 서비스 객체를 만드는 것입니다.

서비스 오브젝트를 사용하여 서비스에 입력을 전송하고 서비스로부터 출력을 수신합니다. 서비스 오브젝트를 작성할 때 인증을 위한 API키 및 사용 중인 watsonx Assistant API의 버전을 지정합니다.

이 Node.js 예제에서 서비스 오브젝트는 assistant 변수에 저장된 AssistantV2의 인스턴스입니다. 다른 언어의 Watson SDK는 서비스 오브젝트를 인스턴스화하는 동등한 메커니즘을 제공합니다.

이 Python 예제에서 서비스 오브젝트는 assistant 변수에 저장된 watson_developer_cloud.AssistantV2의 인스턴스입니다. 다른 언어의 Watson SDK는 서비스 오브젝트를 인스턴스화하는 동등한 메커니즘을 제공합니다.

서비스 개체를 생성한 후에는 상태 비저장 message 메서드를 사용하여 어시스턴트에게 메시지를 보내는 데 사용합니다. 이 예제에서는 메시지가 비어 있습니다. 대화를 시작하기 위해 Greet customer 조치를 트리거하려고 하므로 입력 텍스트가 필요하지 않습니다. 그런 다음 리턴된 출력의 generic 배열에서 리턴되는 텍스트 응답을 인쇄합니다.

node <filename.js> 명령을 사용하여 예제 애플리케이션을 실행하십시오.

python3 <filename.py> 명령을 사용하여 예제 애플리케이션을 실행하십시오.

참고: npm install ibm-watson 을 사용하여 Watson SDK for Node.js 을 설치해야 합니다.

참고: pip install --upgrade ibm-watson 또는 easy_install --upgrade ibm-watson 을 사용하여 Python 용 Watson SDK를 설치해야 합니다.

모든 것이 예상대로 작동한다고 가정하면 어시스턴트는 어시스턴트의 출력을 반환하고 앱은 이를 콘솔에 인쇄합니다:

Welcome to the watsonx Assistant example. What's your name?

이 출력은 어시스턴트와 통신했으며 Greet customer 조치에서 지정한 인사말 메시지를 수신했음을 알려줍니다. 하지만 아직 조수의 질문에 답할 수 있는 방법이 없습니다.

사용자 입력 처리

사용자 입력을 처리하기 위해 클라이언트 애플리케이션에 사용자 인터페이스를 추가해야 합니다. 이 예제에서는 작업을 단순하게 유지하고 표준 입력 및 출력을 사용합니다. Node.js 프롬프트 동기화 모듈을 사용할 수 있습니다. ( npm install prompt-sync 을 사용하여 프롬프트 동기화를 설치할 수 있습니다.) Python 3 input 함수를 사용할 수 있습니다.

// Example 2: Adds user input.

const prompt = require('prompt-sync')();
const AssistantV2 = require('ibm-watson/assistant/v2');
const { IamAuthenticator } = require('ibm-watson/auth');

// Create Assistant service object.
const assistant = new AssistantV2({
  version: '2021-11-27',
  authenticator: new IamAuthenticator({
    apikey: '{apikey}', // replace with API key
  }),
  url: '{url}', // replace with URL
});

const assistantId = '{environment_id}'; // replace with environment ID

// Start conversation with empty message
messageInput = {
  messageType: 'text',
  text: '',
};
sendMessage(messageInput);

// Send message to assistant.
function sendMessage(messageInput) {
  assistant
    .messageStateless({
      assistantId,
      input: messageInput,
    })
    .then(res => {
      processResult(res.result);
    })
    .catch(err => {
      console.log(err); // something went wrong
    });
}

// Process the result.
function processResult(result) {

  // Print responses from actions, if any. Supports only text responses.
  if (result.output.generic) {
    if (result.output.generic.length > 0) {
      result.output.generic.forEach( response => {
        if (response.response_type === 'text') {
          console.log(response.text);
        }  
      });
    }
  }

  // Prompt for the next round of input unless skip_user_input is true.
  let newMessageFromUser = '';
  if (result.context.global.system.skip_user_input !== true) {
    newMessageFromUser = prompt('>> ');
  }

  if (newMessageFromUser !== 'quit') {
    newMessageInput = {
      messageType: 'text',
      text: newMessageFromUser,
    }
    sendMessage(newMessageInput);
  }
}
# Example 2: Adds user input.

from ibm_watson import AssistantV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

# Create Assistant service object.
authenticator = IAMAuthenticator('{apikey}') # replace with API key
assistant = AssistantV2(
    version = '2021-11-27',
    authenticator = authenticator
)
assistant.set_service_url('{url}') # replace with service instance URL
assistant_id = '{environment_id}' # replace with environment ID

# Initialize with empty value to start the conversation.
message_input = {
    'message_type:': 'text',
    'text': ''
    }

context = None

# Main input/output loop
while message_input['text'] != 'quit':

    # Send message to assistant.
    result = assistant.message_stateless(
        assistant_id,
        input = message_input,
        context=context
    ).get_result()
    context = response['context']

    # Print responses from actions, if any. Supports only text responses.
    if result['output']['generic']:
        for response in result['output']['generic']:
            if response['response_type'] == 'text':
                print(response['text'])

    # Prompt for the next round of input unless skip_user_input is True.
    if not result['context']['global']['system'].get('skip_user_input', False):
        user_input = input('>> ')
        message_input = {
            'text': user_input
        }

이 버전의 애플리케이션은 전과 같은 방식으로 시작됩니다(빈 메시지를 어시스턴트로 보내 대화 시작).

processResult() 함수는 어시스턴트에서 수신된 응답의 텍스트를 표시합니다. 그런 다음, 다음 라운드의 사용자 입력에 대한 프롬프트가 표시됩니다.

그런 다음 어시스턴트에서 수신된 응답의 텍스트를 표시하고 다음 라운드의 사용자 입력에 대한 프롬프트를 표시합니다.

예제에서는 글로벌 컨텍스트 변수 skip_user_input 를 확인하고 이 변수가 trueTrue로 설정되지 않은 경우에만 사용자 입력에 대한 프롬프트를 표시합니다. skip_user_input 변수는 사용자 입력이 필요하지 않은 일부 상황에서 어시스턴트에 의해 설정됩니다 (예를 들어, 어시스턴트가 외부 서비스를 호출했지만 여전히 결과를 대기 중인 경우). 사용자 입력에 대한 프롬프트를 표시하기 전에 항상 이 검사를 수행하는 것이 좋습니다.

대화를 종료하는 방법이 필요하기 때문에 클라이언트 앱은 프로그램이 종료해야 함을 표시하기 위해 리터럴 명령 quit 도 감시합니다.

하지만 여전히 올바르지 않은 내용이 있습니다.

Welcome to the watsonx Assistant example. What's your name?
>> Robert
I'm afraid I don't understand. Please rephrase your question.
>> I want to make an appointment.
What day would you like to come in?
>> Thursday
I'm afraid I don't understand. Please rephrase your question.
>>

어시스턴트가 올바른 인사말로 시작하지만 이름을 말하는 경우에는 이해하지 못합니다. 그리고 약속을 하고 싶다고 말하면, 올바른 조치가 트리거됩니다. 하지만 다시, 후속 질문에 응답하는 시기를 이해하지 못합니다.

그 이유는 상태 비저장( message ) 방식을 사용하기 때문에 대화의 상태 정보를 유지하는 것은 클라이언트 애플리케이션의 책임입니다. 아직 상태를 유지하기 위해 아무것도 하지 않기 때문에 어시스턴트는 모든 사용자 입력을 새로운 대화의 첫 번째 차례로 간주합니다. 질문에 대한 기억이 없기 때문에 사용자의 응답을 새 질문 또는 요청으로 해석하려고 합니다.

상태 유지

대화에 대한 상태 정보는 컨텍스트를 사용하여 유지됩니다. 컨텍스트는 애플리케이션과 어시스턴트 간에 주고받는 객체로, 대화가 진행됨에 따라 보존 및 업데이트할 수 있는 정보를 저장합니다. Stateless message 메소드를 사용하기 때문에 어시스턴트는 컨텍스트를 저장하지 않으므로 대화의 한 차례에서 다음 대화로 유지하는 것이 클라이언트 애플리케이션의 책임입니다.

컨텍스트에는 각 대화에 대한 세션 ID와 대화가 진행될 때마다 증가하는 카운터가 포함됩니다. 어시스턴트는 컨텍스트를 업데이트하고 각 응답으로 이를 리턴합니다. 하지만 이전 버전의 예제에서는 컨텍스트를 보존하지 않았기 때문에 이러한 업데이트가 유실되었으며 각 입력 라운드는 새로운 대화의 시작인 것처럼 표시됩니다. 컨텍스트를 저장하고 매번 어시스턴트에게 다시 보내면 이 문제를 해결할 수 있습니다.

컨텍스트에는 대화에서 우리의 위치를 유지하는 것 외에도 애플리케이션과 어시스턴트 간에 전달하려는 다른 데이터를 저장하는 작업 변수가 포함될 수 있습니다. 예를 들어, 대화 중에 유지하려는 지속적 데이터 (예: 고객의 이름 또는 계정 번호) 또는 추적하려는 기타 데이터 (예: 장바구니 또는 사용자 환경 설정의 컨텐츠) 를 포함할 수 있습니다.

// Example 3: Preserves context to maintain state.

const prompt = require('prompt-sync')();
const AssistantV2 = require('ibm-watson/assistant/v2');
const { IamAuthenticator } = require('ibm-watson/auth');

// Create Assistant service object.
const assistant = new AssistantV2({
  version: '2021-11-27',
  authenticator: new IamAuthenticator({
    apikey: '{apikey}', // replace with API key
  }),
  url: '{url}', // replace with URL
});

const assistantId = '{environment_id}'; // replace with environment ID

// Start conversation with empty message
messageInput = {
  messageType: 'text',
  text: '',
};
context = {};
sendMessage(messageInput);

// Send message to assistant.
function sendMessage(messageInput, context) {
  assistant
    .messageStateless({
      assistantId,
      input: messageInput,
      context: context,
    })
    .then(res => {
      processResult(res.result);
    })
    .catch(err => {
      console.log(err); // something went wrong
    });
}

// Process the result.
function processResult(result) {

  let context = result.context;

  // Print responses from actions, if any. Supports only text responses.
  if (result.output.generic) {
    if (result.output.generic.length > 0) {
      result.output.generic.forEach( response => {
        if (response.response_type === 'text') {
          console.log(response.text);
        }  
      });
    }
  }

  // Prompt for the next round of input unless skip_user_input is true.
  let newMessageFromUser = '';
  if (result.context.global.system.skip_user_input !== true) {
    newMessageFromUser = prompt('>> ');
  }

  if (newMessageFromUser !== 'quit') {
    newMessageInput = {
      messageType: 'text',
      text: newMessageFromUser,
    }
    sendMessage(newMessageInput, context);
  }
}
# Example 3: Preserves context to maintain state.

from ibm_watson import AssistantV2
from ibm_cloud_sdk_core.authenticators import IAMAuthenticator

# Create Assistant service object.
authenticator = IAMAuthenticator('{apikey}') # replace with API key
assistant = AssistantV2(
    version = '2021-11-27',
    authenticator = authenticator
)
assistant.set_service_url('{url}') # replace with service instance URL
assistant_id = '{environment_id}' # replace with environment ID

# Initialize with empty message to start the conversation.
message_input = {
    'message_type:': 'text',
    'text': ''
    }
context = {}

# Initialize with empty message to start the conversation.
message_input = {
    'message_type:': 'text',
    'text': ''
    }
context = {}

# Main input/output loop
while message_input['text'] != 'quit':

    # Send message to assistant.
    result = assistant.message_stateless(
        assistant_id,
        input = message_input,
        context = context
    ).get_result()

    context = result['context']

    # Print responses from actions, if any. Supports only text responses.
    if result['output']['generic']:
        for response in result['output']['generic']:
            if response['response_type'] == 'text':
                print(response['text'])

    # Prompt for the next round of input unless skip_user_input is True.
    if not result['context']['global']['system'].get('skip_user_input', False):
        user_input = input('>> ')
        message_input = {
            'text': user_input
        }

이전 예제에서 유일한 변경 사항은 이제 어시스턴트로부터 받은 컨텍스트를 context 이라는 변수에 저장하고 다음 사용자 입력과 함께 다시 전송한다는 점입니다:

이전 예제에서 유일한 변경 사항은 이제 어시스턴트로부터 받은 컨텍스트를 context 이라는 변수에 저장하고 다음 사용자 입력과 함께 다시 전송한다는 점입니다:

  assistant
    .messageStateless({
      assistantId,
      input: messageInput,
      context: context,
    })
response = assistant.message_stateless(
    assistant_id,
    input = message_input,
    context = context
).get_result()

이렇게 하면 컨텍스트가 하나의 대화 턴에서 다음 턴까지 유지되므로 watsonx Assistant 서비스가 더 이상 각 대화를 처음으로 간주하지 않습니다.

Welcome to the watsonx Assistant example. What's your name?
>> Robert
Hi, Robert! How can I help you?
>> I want to make an appointment.
What day would you like to come in?
>> Next Monday
What time works for you?
>> 10 AM
OK, Robert. You have an appointment for 10:00 AM on Sep 12. See you then!

성공! 이제 애플리케이션은 watsonx Assistant 서비스를 사용하여 자연어 입력을 이해하고 적절한 응답을 표시합니다.

이 단순 예제는 어시스턴트와 통신하기 위해 사용자 정의 클라이언트 앱을 빌드하는 방법을 보여줍니다. 실제 애플리케이션은 보다 정교한 사용자 인터페이스를 사용하며 고객 데이터베이스 또는 기타 비즈니스 시스템과 같은 다른 애플리케이션과 통합될 수 있습니다. 또한 각 고유 사용자를 식별하기 위해 사용자 ID와 같은 더 많은 데이터를 어시스턴트에게 보내야 합니다. 하지만 애플리케이션이 watsonx Assistant 서비스와 상호작용하는 방법에 대한 기본 원칙은 동일합니다.

명확한 질문 포함

어시스턴트에서 둘 이상의 조치가 고객의 요청을 이행할 수 있음을 발견하면 자동으로 설명을 요청할 수 있습니다. 자세한 정보는 명확한 질문 을 참조하십시오.

사용자 정의 클라이언트에 명확한 질문을 포함하려면 다음을 수행해야 합니다.

각 설명 제안에는 다음이 포함됩니다.

  • 고객에게 표시할 수 있는 레이블
  • 사용자가 해당 제안을 선택하는 경우 어시스턴트에 전송되는 입력을 지정하는 값입니다.

애플리케이션에서 설명 제안을 구현하려면 다음을 수행하십시오.

  1. 새 입력 오브젝트를 빌드하는 대신 선택된 제안의 value.input 오브젝트를 다음 메시지 입력 라운드로 사용하십시오. 그런 다음 어시스턴트는 시작할 제안 옵션과 연관된 조치를 트리거하여 응답합니다.

  2. 분석 페이지에서 사용자 정의 클라이언트를 사용하여 이를 올바르게 구현했는지 확인하십시오. 설명을 트리거하는 입력을 입력한 후 위 항목 없음 옵션을 클릭하십시오. 대화 에서 요청을 볼 때 설명을 시작한 사용자 요청이 인식되지 않음으로 표시되는지 확인하십시오. 이는 클라이언트가 설명 입력을 어시스턴트에 올바르게 전송하고 있음을 나타냅니다.

v1 런타임 API 사용

v2 API 사용은 watsonx Assistant 서비스와 통신하는 런타임 클라이언트 애플리케이션을 빌드하는 데 권장되는 방법입니다. 그러나 일부 이전 애플리케이션은 대화 상자 스킬 내에서 작업공간으로 메시지를 전송하는 유사한 메소드를 포함하는 v1 런타임 API를 계속 사용할 수 있습니다. 앱이 v1 런타임 API를 사용하는 경우 어시스턴트의 스킬 오케스트레이션 및 상태 관리 기능을 우회하여 워크스페이스와 직접 통신합니다.

v1 /message 메서드 및 컨텍스트에 대한 자세한 내용은 v1 API 참조를 참조 하세요.