Disclaimer

Данный блог является моей личной точкой зрения и не обязательно отражает точку зрения Oracle.

The views expressed on this blog are my own and do not necessarily reflect the views of Oracle

Поиск

Подписка

Создание Inline Service в среде Oracle Real-Time Decisions (RTD)

03.09.2009 от aryndin99

 

Обзор

Beta версия :)

Платформа Oracle Real-Time Decisions (Oracle RTD) позволяет разрабатывать корпоративные программные решения, которые анализируют поведение бизнес процесс и открывающиеся возможности (opportunities) по мере их появления. В этой статье я расскажу, как конфигурировать, разворачивать, анализировать и обновлять Inline Service. Под Inline Service мы будем понимать сконфигурированное приложение, которое развернуто с использованием компонентов RTD. Oracle RTD состоит из пяти компонентов: Decision Studio, Real-Time Decision Server, Decision Center, Administration (JMX), и Load Generator. Inline Service конфигурируются и разворачиваются с использованием Decision Studio, анализ и изменение параметров работы осуществляется через Decision Center. Inlive Service работают на базе Real-Time Decision Server. Inlive Service может собирать и анализировать характеристики корпоративных бизнес процессов непрерывно в реальном времени. Он также используется эти данные и аналитические алгоритмы для принятия решений и формирования обратной связи с бизнес-процессами.


Сценарий

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

Предварительные требования

Прежде чем приступать к дальнейшему чтению, я рекомендую проверить, что выполнены следующие предварительные требования:

  1. Иметь доступ к проинсталлированному Oracle Real-Time Decisions (RTD), включая данные, идущие в поставке примеров CrossSell. Я ранее рассказывал, как проинсталлировать Oracle RTD для Oracle Weblogic.
  2. Если инсталляция сервера выполнена на Unix, то нужно иметь Windows-компьютер, на котором проинсталлирована клиентская часть
  3. Настроить пользователя rtdadmin с использованием JMX.
  4. Скачать текст программных кодов.

Создаем новый Inline Service

Наша цель – создать новый Inline Service. Задачей Inline Service будет извлекать информацию о клиенте из источника данных. Будет использован минимальный набор компонент: источники данных (data source), сущности (entity) и информаторы (Informant). Позже мы добавим больше функционала.

Для создания Inline Service выполняем следующие шаги:

  • Создаем Inline Service проект
  • Конфигурируем элемент Application
  • Создаем источник данных и импортируем поля данных
  • Создаем и сопоставляем сущности
  • Разворачиваем и тестируем Inline Service
Для создания нового проекта Inline Service, мы выполняем следующие шаги:

1. Запускаем Decision Studio (по сути это плагин для Eclispe) на компьютере, где проинсталлированы клиент Oracle RTD: RTD_HOME\eclipse\eclipse.exe, где RTD_HOME это каталог, в который проинсталлирован Oracle RTD. Например, C:\OracleBI\RTD\.

2. Выбираем File > New > Inline Service Project.

3. Вводим Tutorial в качестве имени проекта

4. Выбираем Basic Template из списка шаблонов метаданных.

5. Проверяет, что выбран пункт Create new project in workspace .

image

6. Выберите Finish

Для конфигурации элемента Application, выполним следующие действия:

1. В Inline Service Explorer, развернем папку Tutorial > Service Metadata

image

2. Два раза щелкнем на элементе Application и введем описание в поле Description

image

3. Перейдем на закладку Permissions, нажмем кнопку Add, затем Select Server.

4. Откроектся окно Connect to a server, введем необходимую для подключения к серверу информацию (см. инсталляцию Oracle RTD). Проверьте соединение, нажав Connect.

image

5. При необходимости можно назначить права, но если инсталляция была проведена по инструкции, то наш пользователь rtdadmin уже является членом роли RTDAdministrators, а следовательно имеет все права.

image

Создадим источник данных и импортируем таблицы:

1. Щелкнем правой кнопкой Data Sources в Inline Service Explorer и выберем New SQL Data Source

2. Введем метку источника данные: Customer Data Source. Обратите внимание, что ID заполнится автоматически.

3. В открывшемся окне нажмем кнопку Import. Введем информацию для подключения к сервису.

4. В источниках данных выберем SDDS. В качестве таблицы выберем CROSSSELLCUSTOMERS. Затем нажмем Finish.

5. Выделим столбец ID и с помощью стрелки перенесем его вправо в Input List. Этот столбец будет использоваться, чтобы идентифицировать текущего обрабатываемого заказчика. ID будет поступать из внешнего источника – например из системы аутенфикации клиента (если самообслуживание), либо из CRM системы, если обслуживание ведется в контактном центре.

6. Также оставим только необходимые столбцы:
Age
HasCreditProtection
Language
LastStatementBalance
MaritalStatus
NumberOfChildren
Occupation

image 7. Введем описание и сохраним источник данных.

Создание и сопоставление сущностей.

Источники данных – это достаточно низкоуровневые объекты. Для более высокоуровневой работы используются сущности, которые могут представлять информацию из источников данных, но также могут включать и информацию, полученную другим путем (например, от информаторов).

Создадим сущность для атрибутов заказчика

1. Щелкнем правой кнопкой на элементе Entities в дереве Inline Service Explorer и выберем New Entity.

2. В качестве Display Label введем Customer. Нажмем OK.

3. В открывшемся окне нажмем кнопку Import, выберем созданный ранее источник. Нажмем OK. В результате импортируются все атрибуты. Для этих атрибутов установим значения по-умолчанию.

image

4. Нажмем кнопку Add Key. В поле Display Label введем  customerId (обратите внимание, что имена чувствительны к регистру). Тип данных выберем Integer.

image

5. Нажмем ОК, чтобы сохранить изменения. Затем выберем меню File > Save All.

Создание сущности, поддерживаемой в рамках сессии.

1. Два раза щелкнем на сущность Session.

2. Добавим атрибут (Add Atribute) с именем customer. Тип данных выберем Other. В списке типов сущностей найдем недавно созданный тип Customer.

image

3. Нажмем два раза OK. И затем нажмем кнопку Select, чтобы указать поле, используемое в качестве идентификатора сессии. Выберем customerId. Нажмем ОК.

image

4. Сохраним все: File > Save All.

Сопоставим атрибуты сущностей и источника данных.

1. Откроем для редактирования сущность Customers и перейдем на закладку Mapping. Все поля уже сопоставлены. Осталось только поле ID в списке Data Source Input Values. Сопоставим его.

2. Щелкните на три точки для открытия диалогового окна

image

3. Выберем Attribute or Variable, а заем в дереве выберем Session > customer > customerId

image

4. Нажмем ОК и все сохраним.

 

Разворачиваем и тестируем Inline Service
Создаем информаторов для тестирования Inline Service.

1. В Inline Service Explorer выбираем Integration Points, затем щелкаем Informants правой кнопкой и выбираем – New Informant. Вводим названия информатора – Testing. Нажмем ОК.

2. Нажмем кнопку Advanced в окне редактирования информатора. В открывшемся окне снимем галку Show in Decision Center. Нажмем ОК

3. Выберем Session Keys кнопкой Select.

4. В поле Logic введем код

logInfo("Customer age = " + session().getCustomer().getAge());

image

5. Сохраним все.

Развернем Inline Service

1. Выберем в меню Project > Deploy. В открывшемся окне выберем подключение и поставим галки как показано на рисунке:

image

2. Нажмем кнопку Deploy.

Протестируем работу Inline Service

1. Выберем в меню Window > Show View > Test

2. Введем значение 1 в качестве номера клиента и запустим запрос

image

3. Если получите ошибку

Request failed for Integration Point "Testing" in Inline Service "Tutorial".
Error detail:  com.sigmadynamics.exception.SDRuntimeException: A Decision Service request was received from untrusted host, 192.168.92.1
    at com.sigmadynamics.server.kernel.RtisKernelImpl.checkAuthenticated(RtisKernelImpl.java:1605)
    at com.sigmadynamics.server.rtis.servlet.SDHttpServerEndPoint.sdPost(SDHttpServerEndPoint.java:100)

то необходимо разрешить подключение к Inline Service с указанного IP адреса. Сделать это можно через JMX консоль (как настроить смотрите в инсталляции RTD).

image

Создание модели для анализа звонков

Мы выполним следующие шаги:

  • Создадим информаторы и внешние системы
  • Создадим группу вариантов и модель для анализа звонков
  • Выполним первоначальную тренировку модели с помощью утилиты Load Generator
Создадим информаторы и внешние системы

Наша цель в этом разделе создать информаторы и сопоставить их с пользовательской сессией и внешними системами. Мы уже создали Inline Service и протестировали его простейшие функции. Информаторы мы сконфигурируем  принимать ключ сессии с целью привязать данные к конкретным сессиям.

Для создания информатора мы выполним следующие действия:

  • Создадим сущность Звонок (Call)
  • Свяжем сущности Звонок и Сессия
  • Создадим внешние системы
  • Создадим новые информаторы
  • Протестируем и отладим информаторы

Создаем сущность Звонок

1. В Inline Service Explorer, в дереве  выберем Tutorial > Service Metadata > Entities.

2. Щелкнем правой кнопкой на Entities и выберем New Entity.

3. Введем Call в поле Display Label. Нажмем ОК.

4. Перейдем на закладку Definition и нажмем Add Attribute, чтобы добавить новый атрибут

5. Введем agent и тип данных выберем String.

image

6. Аналогично создадим еще 2 поля. Сверьтесь с карткинкой ниже

Display Label Data Type
length Integer
reason code Integer

image

Свяжем сущности Звонок и Сессия

1. Откроем сущность Session для редактирования.

2. Добавим атрибут (Add Attribute). Введем его название (call) и выберем среди типов данных Other…, а затем выберем нужный тип данных (т.е. Entity Types > Call).

3. Сохраним изменения.

Создадим внешние системы

1. В Inline Service Explorer, откроем Integration Points > External Systems.

2. Правой кнопкой по External Systems и выберем New External System.

3. Введем IVR в поле Display Label.
 image

4. Создадим еще одну систему CRM.

Создадим новые информаторы

1. В Inline Service Explorer, в папке Integration Points создадим Информатор (New Informant).

2. Назовем его Call Begin (в поле Display Label).

3. Выберем в качеств ключа сессии (Session Keys) – поле customerId.

4. В поле External System выберем, а в поле Order введем 1.

image

5. На закладке Logic введем программный код

/*Prepopulate customer data during start of call even though the information may not be used until much  later. This is not explicitly necessary since the server will automatically retrieve the information whenever logic in the Inline Service needs it. */

//session().getCustomer().fill();
int CustomerID = session().getCustomer().getCustomerId();
logInfo("Integration Point - CallBegin: Start Session for customerID = " + CustomerID);

image

6. Создадим еще один информатор.

Поле Значение
Display Label Service Complete
Session Keys customer / customerId
External System CRM
Order 2

7. В созданный информатор Service Complete добавим атрибуты

Название атрибута Тип данных Session Attribute
agent String call / agent
length Integer call / length
reason code Integer call / reason code

image

8. Сохраним изменения.

9. Создадим еще один информатор.

Поле Значение
Display Label Call End
Session Keys customer / customerId
External System CRM
Order 5

10. Настроим окончание сессии при вызове данного информатора.

image

11. На закладке Logic введем программный код.

logInfo("Integration Point - CallEnd");
logInfo("***************************");

Протестируем и отладим информаторы

1. Сохраним все File > Save All

2. Выполним развертывание приложения Project > Deploy.

image

3. Протестируем вызов информаторов.

image

image

4. На данный момент мы создали информаторы, которые в формировании предложения не участвуют. Первый информатор сигнализирует о начале звонка, второй говорит, что обслуживание клиента закончено и можно начинать что-то предлагать дополнительное(делать перекрестные продажи), а последний (CallEnd) создан, чтобы показать, что общение закончено. Информаторы, работающие до формирования предложения обычно служат, чтобы начать работу и получить максимум информации о клиенте. Остался незаконченным пока что Get Cross Sell Offer – это ключевой элемент, который будет использоваться для формирования предложения. Давайте приступ к этому элементу.

image

Создадим группы выбора (choice groups) и модель для анализа звонков.
  • Создадим группу выбора
  • Создадим модель группы
  • Протестируем модель
Создадим группу выбора

1. В Inline Services Explorer, выберем Tutorial > Service Metadata > Choices.

2. Щелкнем правой кнопкой и выбрем New Choice Group.

3. Введем название группы Call Reason в поле Display Label.

4. У всех вариантов в группе выбора будет атрибут под названием code (помните наш reason code, который мы передаем в систему в информаторе Service Complete?) и типом данных Integer. Добавим это атрибут для группы Call Reason.

image

5. Щелкнув правой кнопкой на нашу группу Call Reason в дерем Inline Service Explorer и выбираем New Choice. В поле Display Label введем Check Balance. Нажмем OK.

6. В поле поле значения атрибута code введем 17.

image

7. Создадим еще 3 варианта по таблице.

Choice Code
Make Payment 18
Rate Inquiry 19
Other 20

8. Сохраним все File > Save All

image 

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

1. Выберем Tutorial > Service Metadata > Models

2. Создадим новую модель, щелкнув правой кнопкой и выбрав New Choice Model.

3. Назовем модель Reason Analysis

4. В открывшемся окне уберем галку Use for prediction, а для анализа выберем созданную нами группу Call Reason, а поле Label for Choice введем Reason for call.

image

5. Теперь укажем, когда должна запускаться модель. Для этого на закладке Learn Location укажем интеграционную точку – Service Complete

image

6. Вернемся теперь к информатору Service Complete и введем программный код на закладке Logic

logInfo ("Integration Point - Service Complete. ");
logInfo ("  Reason Code: " + session().getCall().getReasonCode());
logInfo ("  Agent: " + session().getCall().getAgent());
logInfo ("  Length: " + session().getCall().getLength());

int code=session().getCall().getReasonCode();
switch (code) {
  case 17:
      ReasonAnalysis.addToChoice("CheckBalance");
      logInfo ("  CheckBalance was added to the model");    
    break;
  case 18:
      ReasonAnalysis.addToChoice("MakePayment");
      logInfo ("  MakePayment was added to the model");
    break;
  case 19:
      ReasonAnalysis.addToChoice("RateInquiry");
      logInfo ("  RateInquiry was added to the model");
    break;
  default:
      ReasonAnalysis.addToChoice("Other");
      logInfo ("  Other was added to the model");
    break;
}

7. На данный момент наше приложение можно описать следующей диаграммой

image

 

 

Протестируем модель

1. Выполним развертывание приложения Project > Deploy

2. В представлении Test выберем информатор Sevice Complete и введем следующие значения

customerId 7
agent John
length 21
reasonCode 18

image

3. Зайдем в Decision Cetner по адресу http://rtdserver:port/ui, введем имя и пароль. Перейдем по дереву слева Tutorial > Decision Process > Call Reason.

4. Слева откроется диаграмма, на закладке Performance появится диаграмма показывающая то, какой выбор был осуществлен позвонившими клиентами. Эта информация может быть использована аналитиками для анализа ситуации. Если варианты распределить по группам (так чтобы группы имели двойную вложенность), то можно использовать галочку Rollup для того, чтобы свернуть данные на графике по результатам групп.

image 

 

Выполним первоначальную тренировку модели с помощью утилиты Load Generator
  • Создадим скрипт для Load Generator
  • Добавим переменные в скрипт Load Generator
  • Добавим интеграционные точки (информаторы) в скрипт
  • Запустим скрипт и просмотрим результаты в Decision Center
Создадим скрипт для Load Generator

1. Запустим Load Generator на Windows-компьютере (на Unix-системах его нет). RTD_HOME\scripts\loadgen.cmd.

2. Выберем Create a new Load Generator script.

3. На закладке укажем указан файл конфигурации клиента C:\OracleBI\RTD\client\clientHttpEndPoints.properties. Этот файл содержит настройки подключения к серверу. По умолчанию это HTTP1.url = http://localhost:8080. Необходимо изменить этот файл, чтобы он указывал на ваш сервер.

4. В поле Inline Service введите Tutorial. Выберите в поле Think Time значение Fixed Global Think Time. В поле Constant (пауза между посылкой ответов) введите 0. Укажите количество параллельных скриптов(Number of Concurrent Scripts to Run) 1, а количество загрузок(Maximum Number of Scripts to Run) 2000 
image

 

Добавим переменные в скрипт Load Generator

1. Перейдем на закладку Variables

2. Щелкнем правой кнопкой на Script и выберем Add Variable.

3. В названии введем var_customerId, установим Integer Range и диапазон от 1 до 2000. Тип доступа – Sequential.

image

4. Создадим еще 2 переменные.

Variable Name Content Type Minimum Maximum Access Type
var_reasonCode Integer Range 17 20 Random
var_length Integer Range 75 267 Sequential
var_agent String Array John, Peter, Mary, Sara   Random

Переменную var_agent мы создаем строковой и вводим 4 предопределенных значения, которые будут чередоваться случайным образом.

image

 

Добавим интеграционные точки (информаторы) в скрипт

1. Перейдем на закладку Edit Script

2. Щелкнем правой кнопкой в пустом окне дерева и выберем Add Action.

3. В типе действия выберем Message, в качестве точки интеграции введем CallBegin.

3. Щелкнем Input Fields правой кнопкой и выберем Add Item.

4. В поле Name введем Enter customerId, в поле Variable выберем var_customerId. Установим галку Session Key.

image

5. Создадим еще одно действие с именем интеграционной точки ServiceComplete и со следующими параметрами

Name Variables
customerId var_customerId
reasonCode var_reasonCode
agent var_agent
length var_length

6. Параметр customerId выберем в качестве Session Key.

image

7. Создадим еще одно действие с именем интеграционной точки CallEnd со следующими параметрами (выберем этот параметр как ключ сессии).

Name Variables
customerId var_customerId

image

8. В поле Name введем Enter customerId, в поле Variable выберем var_customerId. Установим галку Session Key.

9. Сохраним скрипт.

Запустим скрипт и просмотрим результаты в Decision Center

1. Перейдем на закладку Run

2. Выберем Run > Run

3. Проверим, что не будут возникать ошибки.

image

4. Опять перейдем в Decision Center по адресу http://rtdserver:port/ui, введем имя и пароль.

5. Откроем наш Inline Service.

6. Выберем в дереве группу вариантов Call Reason и перейдем опять на закладку Performance. Варианты распределились примерно равномерно чего и следовало ожидать.

image

7. Выберем слева вариант Make Paymment и перейдем на закладку Analysis. Мы увидим следующую картину

image

8. Из этой информации видно, что call reason code очень сильно кореллирует с выбором Make Payment. Это очевидный и тривиальный факт, т.к. это поле определяет значение, передаваемое модели.

9. Чтобы убрать это поле из анализа щелкнем 2 раза на модели Reason Analysis в Decision Studio. Перейдем на закладку Attribute и введем данное поле в Exclude Attributes:

image

10. Сохраним проект и выполним повторное развертывание.

11. Для того, чтобы очистить результаты тренировки модели необходимо с помощью JConsole дать команду серверу. Для этого запустим JDK_HOME/bin/jconsole.exe и подключимся удаленно к серверу RTD. Как настроить JConsole смотрите в конце статьи Инсталляция RTD для Weblogic. Я буду использовать JConsole из комплекта JDK 6.

image

12. После подключения к системе перейдем на закладку MBeans. В дереве объектов выберем OracleRTD > InlineServiceManager > Tutorial > Development > Loadable > Operations

image

13. Выберем deleteAllOperationalData( ). Это займет пару секунд. После окончания выполнения процедуры все данные, накопленные моделью будут очищены.

14. Перейдем опять в Decision Center мы увидим, что данные изменились и не отражают тривиальную корелляцию с call reason. Из полученных данных видно, что самым лучшим клиентом для нас является 54-55 летний человек, позвонивший проверить баланс и разговаривавший с оператором в течение 99-103 секунд. Модель некачественная, что показывается параметром Model Quality. Очевидно, что на случайно сгенерированных данных и могло возникнуть сколь бы то ни было точной модели.

image

 

Формирование предложений исходя из целей оптимизации

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

Выполним следующие шаги:

  • Создадим группу вариантов
  • Создадим варианты
  • Выберем цели оптимизации
  • Создадим правило для расчета очков (scoring rule) для случая, когда очки будут расчитываться динамически на основе других параметров
  • Назначим очки для вариантов группы
  • Создадим решения
  • Создадим советника (Advisor)
  • Протестируем
Создадим группу вариантов

1. Запустим Decision Studio. Перейдем Tutorial > Service Metadata > Choices.

2. Создадим новую группу вариантов (New Choice Group) с именем Cross Selling Offer.

3. Для группы зададим следующие атрибуты. Сохраним все.


Attribute Data Type Send to client Overridable
Agent Script String Включить Включить
Offer Description String Включить Включить
URL String Включить Включить

image


Создадим варианты

1. Выберем созданную группу и внутри нее создадим следующие варианты (New Choice):

Choice Agent Script Offer Description URL
Brokerage Account Would you like to try our new brokerage account? Brokerage Account offer http://www.offer.com/offer1.html
Credit Card Would you like to try our new credit card? Credit Card offer http://www.offer.com/offer2.html
Life Insurance Would you like to try our new life insurance? Life Insurance offer http://www.offer.com/offer3.html
Roth IRA Would you like to try our new Roth IRA? Roth IRA offer http://www.offer.com/offer4.html
Savings Account Would you like to try our new savings account? Savings Account offer http://www.offer.com/offer5.html

2. Сохраните все.
image

 

Выберем цели оптимизации

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

1. Выберем Tutorial > Service Metadata > Performance Goal.  Щелкнем 2 раза.

2. Нажмем кнопку Add. Введем название цели – Cost. Нажмем OK.

3. Для созданной цели мы выберем направление оптимизации – будем минимизировать стоимость, т.е. Minimize.

image

4. Откроем созданную нами группу вариантов Cross Selling Offer и на закладке Scores добавим созданную цель. Тем самым мы задали, что варианты будут  оцениваться с точки зрения стоимости.

image

После этого необходимо прописать стоимость  для групп и вариантов. Стоимость может задаваться статическим значением, а может вычисляться динамически на основе правил (например, если возраст клиента до 45 лет, то стоимость страхования будет ниже, чем если возраст более 60 лет).

Создадим правило для расчета очков (scoring rule) для случая, когда очки будут расчитываться динамически на основе других параметров

1. Создадим внутри папки Scoring Rules новое правило с именем Credit Card Score.

image

2. Щелкнем правой кнопкой по заголовку Value и выберем Add Condition.

3. В левом поле для ввода выберем атрибут AGE

image

4. В поле ввода для оператора сравнения введем <=, а во второе поле ввода введем константу 40. Результирующее значение выберем равным 130 (следует читать, если возраст меньше либо равен 40, то стоимость 130). В поле Otherwise… введем 147 (это говорит о том, что если возраст больше 40 – стоимость будет считаться равной 147).

image

5. Сохраним все.

Назначим очки для вариантов группы

1. Откроем вариант Brokerage Account в группе Cross Selling Offer. И назначим ему очки – 150.

image

2. Аналогично введем очки для остальных вариантов, кроме Credit Card.

Вариант Очки
Life Insurance 140
Roth IRA 145
Savings Account 135

3. Теперь откроем вариант Credit Card и назначим правило расчета очков, созданное ранее. Для этого нажмем на троеточие, выберем Function or rule call, а затем созданное ранее правило Credit Card Score.

image

4. Сохраним изменения.

Создадим решения

Задача решения – комбинировать цели определенным образом и на базе этой комбинации делать вывод о принятии того или иного варианта.

1. Щелкнем правой кнопкой по Tutorial > Service Metadata > Decisions и выберем New Decision.

2. Введем название Select Offer. Нажмем ОК.

3. Нажмем кнопку Select, чтобы выбрать группу, которую будет анализировать решение. Выберем группу Cross Selling Offer. Нажмем ОК.

image

4. Создадим второе такое же решение. Назовем его Random Choice, но в этом решении выберем пункт Select at random.

image 

Создадим советника (Advisor)

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

1. В Inline Service Explorer, выберем Tutorial > Service Metadata > Integration Points > Advisors.

2. Щелкнем правой кнопкой и создадим нового советника с именем Get Cross Sell Offer.

3. На закладке Request выберем ключ сессии customer / customerId. Выберем CRM в списке внешних систем. Выберем также этап, на котором выполняется помощник – 3.

image

4. На закладке Response выберем решение – Select Offer. Для контрольной группы (Control Group Decision) выберем Random Choice. В качестве варианта по-умолчанию выберем Cross Selling Offer > Life Insurance. Этот вариант будет выдан в качестве рекомендации, если оказалось невозможным подбрать подходящий вариант за разумное время.

image

5. Перейдем на закладку Asynchronous Logic и введем программный код

logInfo("Integration Point - Get Cross Sell Offer");
logInfo("  Customer age = " + session().getCustomer().getAge() );// 'choices' is array returned by the 'Select Offer' decision
if (choices.size() > 0) {
  //Get the first offer from array
  Choice offer = choices.get(0);
  logInfo("  Offer presented: '" + offer.getSDOLabel() + "'");
}

6. Сохраним, выполним развертывание и протестируем сервис

customerId 7

image

customerId 55

image

7. Перейдем в Decision Center. Выберем Integration Map – диаграмма должна выглядеть следующим образом.

image

Конфигурируем Inline Service для изучения поведения клиентов в плане принятия или непринятия предложения

До настоящего момента мы строили сервис, который анализирует причины звонков клиентов, различные характеристики (как, например, возраст) и, учитывая заданные нами бизнес-правила, предлагает вариант.

Предложенный вариант может быть принят или непринят клиентом. Возможно клиент заинтересуется предложением, но решения примет не сразу. Нам необходимо изучать это поведение и делать такие предложения, которые не только интересны нам (например, с точки зрения заработка), но и интересны клиентам. Inline Service позволяет проводить такую работу.

Для конфигурации анализа принятия или неприятия предложения выполним следующие действия:

  • Добавим модель для изучения принятия предложений
  • Выполним первоначальное обучение модели
Добавим модель для изучения принятия предложений
  • Создадим события для предложений
  • Создадим модель анализа событий
  • Сконфигурируем сущность сессии для запоминания предложений
  • Изменим поведения советника Get Cross Sell Offer, чтобы он запоминал выполненное предложение
  • Создадим информаторов для отслеживания ответов
  • Протестируем информатор, отслеживающий ответы
Создадим события для предложений

1. В Decision Studio откройте группу вариантов Cross Selling Offer. Перейдем на закладку Choice Events.

2. Добавим 2 события Presented и Accepted.

image

Создадим модель анализа событий

1. Щелкнем правой кнопкой пункту Models и выберем New Choice Event Model. Назовем модель Offer Acceptance Predictor.

2. В настройках модели уберем галку Default time window. Временное окно выберем – Week. Группу выберем Cross Selling Offer. Основное событие – Presented. Положительный выход – Accepted.

image

3. На закладке Learn Location выберем момент обучения – On session close.

4. Сохраним все.

Сконфигурируем сущность сессии для запоминания предложений

Откроем сущность Session и добавим атрибут:

Display Label Offer Extended
Data Type String
Show in Decision Center Unchecked
Use for analysis Unchecked

image

Изменим поведения советника Get Cross Sell Offer, чтобы он запоминал выполненное предложение

1. Откроем советника Get Cross Sell Offer, перейдем на закладку Asynchronous Logic.

2. Заменим программный код на следующий

logInfo("Integration Point - Get Cross Sell Offer");
logInfo("  Customer age = " + session().getCustomer().getAge() );
// 'choices' is array returned by the 'Select Offer' decision
if (choices.size() > 0) {
  //Get the first offer from array
  Choice offer = choices.get(0);
  //For the selected offer, record that it has been 'presented'
  offer.recordEvent("Presented"); 
  //Set the session attribute 'OfferExtended' with the offer's ID.
  session().setOfferExtended(offer.getSDOId());
  logInfo("  Offer presented: '" + offer.getSDOLabel() + "'");
}

Создадим информаторов для отслеживания ответов

1. Создадим новый информатор с названием Offer Feedback. Установим для него External System равной CRM, а порядок выполнения 4. Ключом сессии выберем customerId.

2. Добавим атрибут Positive типа String.

3. На закладке Logic добавим программный код.

logInfo("Integration Point - Offer Feedback");
//"yes" or "no" to accept offer.
String    positive = request.getPositive();
positive = positive.toLowerCase();

//Get the offer id from session attribute 'OfferExtended'
String extendedOfferID = session().getOfferExtended();
if (extendedOfferID != null) {
   //Get the offer from choice group 'Cross Selling Offer'
   Choice offer = CrossSellingOffer.getChoice(extendedOfferID);
   if (offer != null){
        String offerId = offer.getSDOId();
        //If response is "yes", then record the offer as accepted.
        if (positive.equals("yes")) {
            offer.recordEvent ("Accepted");
            logInfo("  Offer '" + offer.getSDOLabel() + "' accepted");
        }
   }
}

4. Сохраним все.

Протестируем информатор, отслеживающий ответы

1. Выполним развертывание проекта.

2. Запустим советника Get Cross Sell Offer и на вход подадим номер клиента 10.

image

3. Сформируем ответ клиента 10, введем в качестве ответа yes.

image

 

Выполним первоначальное обучение модели
  • Создадим скрипт Load Generator
  • Очистим статистику и историю обучения
  • Запустим скрипт наполнения.

Создадим скрипт Load Generator

1. Запусти Load Generator и откроем ранее созданный скрипт.

2. Добавим переменную var_positive. Содержимое переменной выставим Weighted String Array (взвешенный набор строк – каждой строке можно сопоставить % времени, когда она будет появляться). Введем 2 строки: yes – 30%, no – 20%.

image

3. Откроем закладку Edit Script. В левой панели добавим еще одно действие, щелкнув правой кнопкой и выбрав Add Action.  Тип события выберем Message, а точку контакта – GetCrossSellOffer. В списке полей добавим поле customerId и значение для этого поля будем брать из переменной var_customerId. Укажем, что это ключ сессии.

4. Переместим это действие в позицию после Service Complete, щелкнув на действии правой кнопкой и выбрав Move Up.

image

5. Создадим еще одной действие с интеграционной точкой OfferFeedback. В этом действии будет 2 поля:

Поле Переменная
customerId var_customerId
positive var_positive

6. Также переместим его в позицию до CallEnd.

image

7. Сохраним настройки.

Очистим статистику и историю обучения

1. Запусти JConsole. Подключимся к серверу RTD.

image

2. Перейдем на закладку Mbeans и выберем OracleRTD > InlineServiceManager > Tutorial > Development > Loadable > Operations. Выберем операцию deleteAllOperationalData().

image

3. Дождитесь окна и закройте JConsole.

image

 

Запустим скрипт наполнения.

1. В Load Generator перейдем на закладку Run и через меню Run > Run запусти выполнения скрипта. Проверим, что не возникло ошибок.

image

2. Зайдем в Decision Center. Выберем в дереве Decision Process > Cross Selling Offer. Перейдем на закладку Performance.

image

3. Обратите внимание, что выбираются только 2 из 5 предложений. Это отражает ситуацию, когда оптимизация происходит только с точки зрения стоимости. Очки, назначаемые для каждого варианта зависят от возраста. Мы также видим прогнозируемое значение количества принятых предложений – около 30% (это было задано в Load Generator).

 

Используем модель, что повлиять на формирование предложений.
  • Расширим цели оптимизации
  • Выполним наполнение модели
Расширим цели оптимизации
  • Создадим атрибут, показывающий доход от принятия предложения
  • Создадим цель оптимизации – увеличить доход от предложений
  • Изменим решение, чтобы оно включало также метрику Expected Revenue
  • Проверим какие значения вероятности принятия предложения формируются
  • Протестируем логику советника
Создадим атрибут, показывающий доход от принятия предложения

1. Добавим в группу Cross Selling Offer новый атрибут Revenue с типом данные Integer. Проверим, что установлена галка – Отправлять клиенту (Send to client).

image

2. Для варианта Brokerage Account установим значение этого атрибута равным 300.
image

3. Для остальных вариантов установим значения в соответствие с таблицей

Credit Card 205
Life Insurance 185
Roth IRA 190
Savings Account 175
Создадим цель оптимизации – увеличить доход от предложений

1. Откроем Performance Goals и добавим новую цель Expected Revenue с задачей ее максимизации.

image

2. Откроем группу вариантов Cross Selling Offer и добавим новую метрику Expected Revenue.

image

3. Создадим функцию, которая будет вычислять метрику Expected Revenue. Нам понадобится функция перемножение. В дереве Inline Service Explorer щелкаем правой кнопкой на Functions и создаем функцию Multiply.

image

4. Щелкнем на троеточии напротив Expected Revenue, чтобы задать вычисление ожидаемого дохода, выберем Function or rule call, затем функцию Multiply. 

image

5. Для параметра a выберем атрибут вариант Revenue

image

6. Для параметра b соответственно соответственно выберем Model prediction, укажем модель Offer Acceptance Predictor, а событие – Accepted.

image

7. В результате получим для Expected Revenue очки

image

 

8. Посмотрите на метрику Expected Revenue. Эта метрика равна Revenue умножить на вероятность принятия предложения. Вероятность принятия решения это значение от 0 до 1 (1 – это 100% вероятность принятия). Если для предложения A и B будет одинаковый доход, то будет выбрано то предложение, которое будет иметь большую вероятность принятия.

Изменим решение, чтобы оно включало также метрику Expected Revenue

1. Откроем решение Select Offer по адресу Tutorial > Service Metadata > Decisions.

2. Нажмем кнопку Goals и добавим еще одну цель – Expected Revenue.

image

3. Обратите внимание, что оптимизация идет для двух целей и каждая из них равноприоритетна (50%). При необходимости мы может увеличить приорит одной из целей.

Проверим какие значения вероятности принятия предложения формируются

Для этого мы добавим атрибут к варианта, который будет вычисляться динамически и равняться вероятности принятия.

1. Откроем Cross Selling Offer и добавим атрибут Likelihood of Acceptance типа Double. Укажем, что этот атрибут посылается клиенту.

image

2. Зададим формулу для этого атрибута

image

3. Откроем советника Get Cross Sell Offer и вставим на закладке программный код

logInfo("Integration Point - Get Cross Sell Offer");
logInfo("  Customer age = " + session().getCustomer().getAge() );
// 'choices' is array returned by the 'Select Offer' decision.  The
// name 'choices' was set (and can be changed) in the 'Choice Array'
// text box in the 'Select Offer' decision’s 'Pre/Post Selection
// Logic' tab.
if (choices.size() > 0) {
  //Get the first offer from array
  Choice offer = choices.get(0);
  //For the selected offer, record that it has been 'presented'
  offer.recordEvent("Presented"); 
  //Set the session attribute 'OfferExtended' with the offer's ID.
  session().setOfferExtended(offer.getSDOId());
  logInfo("  Offer presented: '" + offer.getSDOLabel() + "'");
  //Cast selected offer to type CrossSellingOfficeChoice -
  //the base Choice type of choice group 'Cross Selling Offer'
  CrossSellingOfferChoice cso = (CrossSellingOfferChoice) offer;
  logInfo("  Likelihood of Acceptance = " + cso.getLikelihoodOfAcceptance());
}

Протестируем логику советника

1. Выполним развертывание сервиса.

2. Вызовем помощника Get Cross Sell Offer со значением 10 для customerId. Если для Likelihood of Acceptance вы получите значение NaN, то это нормально, т.к. модель еще не имеет достаточно данных.

image

Внесем небольшую неопределенность в логику принятия решений

1. До сих пор решения принималось случайным образом (мы прописали это в Load Generator). Теперь мы сделаем небольшое отклонение. Заменим программную логику для информатора Offer Feedback на следующую. Эта логика принимает решение "yes", если предлагается решение LifeInsurance и количество детей больше, чем 1.

logInfo("Integration Point - Offer Feedback");
//"yes" or "no" to accept offer.
String    positive = request.getPositive();
positive = positive.toLowerCase();

//Get the offer id from session attribute 'OfferExtended'
String extendedOfferID = session().getOfferExtended();
if (extendedOfferID != null) {
   //Get the offer from choice group 'Cross Selling Offer'
   Choice offer = CrossSellingOffer.getChoice(extendedOfferID);
   if (offer != null){
        String offerId = offer.getSDOId();
        //Introduce artificial bias for customers with 2 or more
        //children to always accept "LifeInsurance" if it was
        //selected after scoring.
        //If data source is Oracle, change the following method from
        //getNumberOfChildren() to getNumberofchildren()
        int numOfChildren = session().getCustomer().getNumberOfChildren();
        if ( numOfChildren >= 2 && offerId.equals("LifeInsurance")) {
            positive="yes";
        }
        //If response is "yes", then record the offer as accepted.
        if (positive.equals("yes")) {
            offer.recordEvent ("accepted");
            logInfo("  Offer '" + offer.getSDOLabel() + "' accepted");
        }
   }
}

2. Сохраним все.

Выполним наполнение модели

1. Запусти JConsole. Подключимся к серверу RTD.

image

2. Перейдем на закладку Mbeans и выберем OracleRTD > InlineServiceManager > Tutorial > Development > Loadable > Operations. Выберем операцию deleteAllOperationalData().

image

3. Дождитесь окна и закройте JConsole.

image

4. Откроем в Load Generator ранее созданный скрипт и перейдем на закладку Run и через меню Run > Run запусти выполнения скрипта. Проверим, что не возникло ошибок. Поставим скрипт на паузы на коичестве запусков около 200. Посмотрим журнал сервера (у меня этой файл /u01/app/oracle/user_projects/domains/rtd/servers/RTD_Server/logs/RTD_Server.out).

image

 image

5. Продолжим выполнение скрипта.

6. Перейдем в Decision Center, в котором можно видеть информацию о принятых решениях

image

7. Выберем пункт Life Insurance и перейдем на закладку Analysic > Best fit. Из таблицы видно, что именно количество детей равное 2 является основным влияющим на выбор клиентов фактором.

 

Итоги:

Мы рассмотрели следующие темы:

  • Создание Inline Service
  • Создание модели для анализа звонков
  • Генерацию предложений на основе целей оптимизации
  • Конфигурацию Inline Service для изучения принятия/неприятия предложения
  • Использование модели для влияния на генерацию предложений

Рубрики: BEA, Business Intelligence, Oracle Real-Time Decisions | Комментариев нет »

Оставить комментарий

Заметьте: Включена проверка комментариев. Нет смысла повторно отправлять комментарий.