В предыдущих статьях мы изучили, что аналитики хотят узнать об их виртуальном помощнике и некоторых строительных блоках для построения аналитики. В этом посте я продемонстрирую несколько общих рецептов, адаптированных к журналам Watson Assistant.

Базовый уровень: получение необработанных событий журнала

Сначала мы извлекаем необработанные события журнала и сохраняем их в файловой системе. Для этого требуются apikey и URL-адрес для ваших навыков. Для помощника с одним навыком вам также понадобится идентификатор рабочей области (извлекаемый из URL-адреса рабочей области Legacy v1), для помощника с несколькими навыками есть другие идентификаторы, которые вы можете использовать для фильтрации (описанные в журнале списка Watson Assistant API событий ).

Пример подробного описания API:

Skill Name: Sample Skill
Skill ID: 5f34f4e3-c579–4a59-aa87–9fc45098133d
Legacy v1 Workspace URL: https://gateway-wdc.watsonplatform.net/assistant/api/v1/workspaces/5f34f4e3-c579-4a59-aa87-9fc45098133d/message

Соответствующий код записной книжки для этого рецепта выглядит следующим образом, который извлекает до 10 000 событий журнала в период с 1 по 30 ноября 2019 года:

import getAllLogs 
iam_apikey="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
url="https://gateway-wdc.watsonplatform.net/assistant/api"
workspace_id="5f34f4e3-c579–4a59-aa87–9fc45098133d"
log_filter="response_timestamp>=2019–11–01,response_timestamp<2019–11–30"
page_size_limit=500
page_num_limit=20
version="2018–09–20"
rawLogsJson = getAllLogs.getLogs(iam_apikey, url, workspace_id, log_filter, page_size_limit, page_num_limit, version)

Базовый уровень: извлекайте интересующие поля из событий журнала

Затем мы конвертируем необработанные события журнала в формат, подходящий для исследований и анализа данных. Мы извлечем интересующие вас поля и сопоставим необработанные события журнала с беседами.

Требуется соответствующий идентификатор разговора. Для квалифицированного помощника это «response.context.conversation_id». Поля наиболее часто анализируемых событий извлекаются автоматически. При желании вы можете предоставить список дополнительных полей для включения в анализ. Результатом этого шага является фрейм данных Pandas, представляющий данные вашего разговора Watson Assistant.

Этот рецепт выглядит следующим образом для помощника с одним навыком только с полями для примеров. Последний оператор показывает образец из фрейма данных, подтверждающий, что извлечение журнала было успешным.

import extractConversations
primaryLogKey = "response.context.conversation_id"
conversationKey='conversation_id'
customFieldNames = None
allLogsDF = extractConversations.extractConversationData(rawLogsJson, primaryLogKey, customFieldNames)
allLogsDF.head()

Пример вывода:

Рецепт - сколько разговоров?

Бизнес-аналитик начнет с основного вопроса, который обрабатывается с помощью следующего кода.

print("Total log events:",len(allLogsDF))
print("Total conversations:",len(allLogsDF[conversationKey].unique()))

Пример вывода:

Total log events: 10000
Total conversations: 1311

Рецепт - как часто посещается узел диалога?
Бизнес-аналитик также захочет узнать, сколько раз ключевые события происходят в разговоре. События могут включать удовлетворение, эскалацию или любой другой тип события. Эти события связаны с конкретными узлами в диалоговом окне Watson Assistant. Учитывая идентификатор узла для узла диалога, мы можем подсчитать, сколько раз он был посещен.

При использовании редактора диалогового окна Watson Assistant идентификатор узла для данного узла диалогового окна можно найти, щелкнув узел диалогового окна и проверив конец URL-адреса.

node_to_search="node id here like node_5_1546894657426"
node_visits_as_frame = allLogsDF[[node_to_search in x for x in allLogsDF['nodes_visited']]]
print("Total visits to target node:",len(node_visits_as_frame))
print("Unique visitors to target node:",len(node_visits_as_frame[conversationKey].unique()))

Пример вывода:

Total visits to target node: 595
Unique visitors to target node: 586

Рецепт - соберите высказывания пользователей для обучения и тестирования классификатора

Аналитик намерений хочет убедиться, что высказывания пользователей классифицируются по правильным намерениям. В целом этот процесс состоит из трех этапов:

1. Соберите высказывания пользователя, которые должны соответствовать намерениям.

2. Эксперты в предметной области, предоставляющие или подтверждающие намерения

3. Проверка точности и улучшение классификатора.

Шаг 1 показан ниже, шаг 2 настраивается для вашего помощника, а шаг 3 более подробно обрабатывается записной книжкой Анализ навыков диалога.

Важно понимать, что не все высказывания пользователя содержат намерения. Да / нет вопросы типа "Было ли это полезно?" или вопросы о вводе данных, например "Какой идентификатор заказа?" обычно не кодируются намерениями. Таким образом, вам нужно знать, где искать высказывания, содержащие намерения.

Самый простой источник пользовательских высказываний - это первый раз, когда пользователь отправляет текст помощнику. Для этого необходимо знать, какой номер поворота диалогового окна соответствует первому разу пользователя, представленный в переменной USER_FIRST_TURN_COUNTER. «Сначала пользователь» - USER_FIRST_TURN_COUNTER = 1, «сначала помощник» - USER_FIRST_TURN_COUNTER = 2.

Пример кода:

USER_FIRST_TURN_COUNTER=2
userFirstTurnView = allLogsDF[allLogsDF['dialog_turn_counter']==USER_FIRST_TURN_COUNTER]
userFirstTurnDF = userFirstTurnView[["input.text","intent","intent_confidence"]]
userFirstTurnDF.to_csv("utterances.csv",index=False,header=["Utterance", "Predicted Intent", "Prediction Confidence"])
userFirstTurnDF.head()

Пример вывода:

Точно так же мы можем извлечь высказывания, данные в ответ на данный узел диалога, указав его идентификатор узла. В этом рецепте мы смотрим на nodes_visited из предыдущего сообщения, поскольку ожидаемые нами высказывания являются ответами на него, используя поле prev_nodes_visited.

Пример кода:

def responses_to_node(df:pd.DataFrame, node_to_search:str):
   responses_df = df[[node_to_search in x for x in df['prev_nodes_visited']]]
   #Remove conversations that didn't reach this node
   responses_df = responses_df[responses_df['input.text'] != '']
   return responses_df[['input.text','intent','intent_confidence']]
nodeResponsesDF = responses_to_node(allLogsDF, node_to_search)
nodeResponsesDF.head()

Пример вывода:

Рецепт - сбор голосовых ответов на заданный узел диалогового окна

При анализе речи потребуется просмотреть записанные высказывания для данного диалогового узла, чтобы определить, насколько хорошо речевая модель работает для данного типа ответа. Как и в приведенном выше рецепте, используемом аналитиком намерений, мы можем извлечь дополнительные поля, подходящие для просмотра аудиофайлов и транскрипций. Поля message_start и message_end представляют относительное время в вызове, когда пользователю было предложено ответить, и когда он ответил. Дополнительная переменная контекста STT_CONFIDENCE должна быть добавлена ​​через уровень оркестрации помощника, чтобы передать достоверность транскрипции механизма речи в текст.

Пример кода:

def speech_responses_to_node(df:pd.DataFrame, conversationKey:str, node_to_search:str):
   responses_df = df[[node_to_search in x for x in df['prev_nodes_visited']]]
   #Remove conversations that didn't reach this node
   responses_df = responses_df[responses_df['input.text'] != '']
   return responses_df[[conversationKey,'message_start','message_end', 'input.text','intent','intent_confidence','STT_CONFIDENCE']]
voiceResponsesDF = speech_responses_to_node(allLogsDF, conversationKey, node_to_search)
voiceResponsesDF.head()

Пример вывода:

Рецепт - резюмируйте уверенность в намерениях

Аналитику намерений потребуется подробное описание намерений, выбранных помощником, включая их частоту и среднюю достоверность. Усилия по обучению и обслуживанию должны быть сосредоточены на наиболее частых намерениях с наименьшей степенью уверенности. В приведенном ниже примере мы отмечаем, что многие высказывания не классифицируются по намерениям (их всегда следует проверять). Однако мы также можем заметить, что намерения «reset_password» и «ticket_new_request» происходят с высокой частотой и низкой достоверностью, и обновления обучения должны быть сосредоточены на этих проблемных точках.

Пример кода:

userIntentSummaryDF = userFirstTurnDF.groupby('intent',as_index=False).agg({
   'input.text': ['count'],
   'intent_confidence': ['mean']
})
# Rename columns for future ease of use
userIntentSummaryDF.columns=["intent","count","confidence"]
# Increases readability of dashboard reports
if userIntentSummaryDF.loc[0,"intent"]=="":
   userIntentSummaryDF.loc[0,"intent"]="(no intent found)"
# Printing `userIntentSummaryDF` or `userIntentSummaryDF.head()` produces a table but the same data can be visually displayed
intent_heatmap.generateTreemap(userIntentSummaryDF, 'count', 'confidence', 'intent', 'Classifier confidence by intent')

Пример вывода:

Что дальше после этих рецептов?

В этом посте описаны два основных типа рецептов: создание описательных метрик «приборной панели» и извлечение данных для тестирования и обучения ваших моделей.

Для метрик приборной панели следующий шаг - определить, какие метрики требуются вашему бизнесу, и приступить к их внедрению. Общие метрики панели мониторинга включают в себя количество начатых разговоров, количество переходов на более высокий уровень и количество завершенных. Эти показатели часто классифицируются по типу намерений. Многие из этих показателей панели мониторинга достижимы, но с учетом того, сколько разговоров достигают (или не достигают) данного диалогового узла. Блокнот для измерений - хорошая отправная точка для этого расследования.

Для рецептов тест / обучение цель состоит в том, чтобы извлечь выходные данные из модели и оценить, насколько хорошо модель работает. Обычно это требует обзора специалиста в предметной области. С помощью набора высказываний и намерений как от малых и средних предприятий, так и от Watson Assistant вы можете определить точность помощника и то, где необходимо улучшить обучение намерениям. С помощью набора аудиофайлов, транскрипции Watson и транскрипции SME вы можете оценить производительность модели преобразования речи в текст. Анализ навыков диалога и Инструмент тестирования WA - хорошие следующие шаги после того, как вы соберете такие данные.

Обратите внимание, что аналитика, которую вы хотите выполнить, может потребовать модификации вашего Watson Assistant. Один из распространенных способов - добавить помощнику дополнительные контекстные переменные для использования в аналитике. Одним из примеров было наше добавление STT_CONFIDENCE для измерения достоверности транскрипции речи в текст. Вы также можете добавить переменные, указывающие начало, конец или результат какого-либо бизнес-процесса. Многие аналитики возможны с использованием только идентификаторов узлов, намерений и значений достоверности, но вы можете расширить эту аналитику, добавив свои собственные контекстные переменные и проанализировав их.

Код, используемый в этой серии блогов, доступен на сайте WA-Testing-Tool по адресу https://github.com/cognitive-catalyst/WA-Testing-Tool/tree/master/log_analytics.

Выражаем благодарность следующим рецензентам и соавторам этого поста: Эрику Уэйну, Айшварии Харихаран, Одри Холломан, Мохаммаду Горджи-Сефидмазги и Дэниелу Зиска.

За дополнительной помощью в анализе и улучшении Watson Assistant обращайтесь в IBM Data and AI Expert Labs and Learning.