使用 API 建置自訂用戶端
中的自動學習功能 watsonx Assistant
自 2025 年 6 月 16 日起,watsonx Assistant。 此日期之後,自動學習設定會從作業全局設定頁移除,所有自動學習功能也會停用。
如果沒有任何內建整合符合您的需求,您可以透過開發與使用者互動並與 IBM® watsonx™ Assistant 服務進行通訊的自訂用戶端應用程式來部署助理。
Watson SDK 可協助您撰寫與 watsonx Assistant互動的程式碼。 有關 SDK 的更多信息,請參閱 IBM Watson API。
設定助理
我們在中建立的範例應用程式會實作數個簡式函數,以說明用戶端應用程式如何與 watsonx Assistant互動。 應用程式碼會收集輸入並將其傳送至助理,該助理會將應用程式顯示的回應傳送給使用者。
若要自行嘗試此範例,您首先需要設定用戶端所連接的簡式範例助理:
範例動作包括詢問客戶名稱的 Greet customer 動作,以及用於建立及取消預約的簡式動作。
取得服務資訊
若要存取 watsonx Assistant REST API,您的應用程式需要能夠向 IBM Cloud® 進行鑑別,並連接至其部署所在環境中的助理。 您需要複製服務憑證和環境 ID,然後貼到應用程式代碼中。 您還需要服務實例位置的 URL (例如,https://api.us-south.assistant.watson.cloud.ibm.com )。
若要尋找此資訊,請執行下列動作:
-
移至 環境 頁面,然後選擇您要連接的環境。
-
按一下 設定 圖示
圖示,以開啟環境設定。
-
選擇 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 這個範例中,服務物件是 AssistantV2 的一個實體,儲存在變數 assistant 中。 其他語言的 Watson SDK 提供了實體化服務物件的相等機制。
在 Python 這個範例中,服務物件是 watson_developer_cloud.AssistantV2 的一個實體,儲存在變數 assistant 中。 其他語言的 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 prompt-sync 模組。 (您可以使用 npm install prompt-sync 安裝 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 服務互動的基本原則仍會相同。
包括澄清問題
當助理發現多個動作可能滿足客戶的要求時,它可以自動要求釐清。 如需相關資訊,請參閱 詢問釐清問題。
若要包括在自訂用戶端中釐清問題,您需要:
- 顯示從
messageAPI 傳回的說明建議選項 - 在下一輪使用有效負載來呼叫
messageAPI,該有效負載對應於客戶選擇以回答澄清問題的建議選項。 如果您未實作該呼叫,則 自動學習 及 使用無法辨識的要求來取得動作建議 無法正確運作。
每項澄清建議包括:
- 可以向客戶顯示的標籤
- 指定在使用者選擇對應建議時傳送給助理之輸入的值
若要在應用程式中實作澄清建議,請執行下列動作:
使用 v1 runtime API
建議使用第 2 版 API 來建置與 watsonx Assistant 服務通訊的運行環境用戶端應用程式。 不過,有些舊版應用程式可能仍在使用 v1 runtime API,其中包含類似的方法,可在對話技巧中傳送訊息到工作區。 如果您的應用程式使用 v1 runtime API,它會直接與工作區溝通,繞過助理的技能協調和狀態管理功能。
有關 v1 /message 方法和上下文的詳細資訊,請參閱 v1 API Reference。