Статьи

Отслеживание пользовательских путей в IVR с Neo4j

Я начал свою карьеру в области разработки программного обеспечения, написав приложения для колл-центра в небольшом банке во Флориде. Я помню, что банк приобрел любой «Cadillac» систем интерактивного голосового ответа (IVR) за те сумасшедшие деньги. Сегодня вы можете создать IVR за ночь, используя Twilio .

Twilio

Когда вы регистрируетесь в Twilio, вы можете выбрать свой номер телефона (более или менее). Например, я выбрал +1 (636) 451-7411, что означает +1 ( нео ) 4j 1-7 411 . Если вы позвоните по этому номеру прямо сейчас (при условии, что у меня не закончились кредиты Twilio), вы подключитесь к моему IVR.

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

response = Twilio::TwiML::Response.new do |r|
  r.Say "Thank you for calling the Neo4j I V R demo.", :voice => "alice"
  r.Gather :action => "/mainmenu", :numDigits => 1 do
    r.Say "For quality assurance purposes this call may be recorded", :voice => "alice"
    r.Say "For rent payment options and billing questions, press 1", :voice => "alice"
    r.Say "To submit a maintenance request, press 2", :voice => "alice"
    r.Say "For all other tenant related questions press 3", :voice => "alice"
    r.Say "To repeat this message press 9", :voice => "alice"
  end
  r.Say "Sorry, I didn\"t get your response.", :voice => "alice"
  r.Play "http://neo-ivr.herokuapp.com/" + "hello.mp3"
  r.Redirect "/", :method => "GET"
end

Приведенный выше код генерирует XML-файл, который интерпретирует Twilio. Если вы нажмете «2» для отправки запроса на обслуживание, вы получите другое меню, сгенерированное этим кодом:

post "/maintenance" do
  add_event(request, "/maintenance")
  response = Twilio::TwiML::Response.new do |r|
    r.Gather :action => "/maintenance-input", :numDigits => 1 do
      r.Say "if your heat is out, press 1 ", :voice => "alice"
      r.Say "if there is a problem with your plumbing, press 2", :voice => "alice"
      r.Say "for all other maintenance questions, press 3", :voice => "alice"
      r.Say "to return to the previous menu, press 0", :voice => "alice"
      r.Say "to repeat this message press 9", :voice => "alice"
    end
    r.Say "Sorry, I didn\"t get your response.", :voice => "alice"
    r.Play "http://neo-ivr.herokuapp.com/" + "hello.mp3"
    r.Redirect "/maintenance"
  end 
  response.text 
end

Пользователи IVR будут перемещаться по этому меню и сообщать о проблемах, которые у них есть, или отчаянно начинать нажимать кнопки, пока не получат возможность общаться с человеком. Чем дольше они добираются туда, куда им нужно, тем злее они становятся. Если бы только был способ отследить пути через систему … о да … Neo4j .

Проницательный наблюдатель, возможно, заметил вызов метода «add_event» в приведенном выше коде, давайте посмотрим, что он делает:

def add_event(request, url)
    $neo.commit_transaction(["MATCH (old:Event {session: {session}})<-[:PREV*0..]-(latest)
      WHERE NOT(latest<-[:PREV]-())
      WITH latest
      LIMIT 1
      CREATE (latest)<-[:PREV]-(e:Event {session: {session}, url: {url}})
      WITH e
      MATCH (u:User {number: {number}}), (p:Page {url: {url}})
      CREATE (u)-[:DIALED]->(e)-[:ON]->(p)
      RETURN e",
    {:number => request["From"],
     :url => url,
     :session => request["CallSid"]}
     ])
end

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

d3logo

Мы будем использовать библиотеку JavaScript D3 и заимствовать плагин Sankey для нашей визуализации.

sankey_viz

Запрос Cypher, который генерирует эту визуализацию, начинается с корня и проходит на расстоянии до 3 прыжков, подсчитывает пути и возвращает их нам. Небольшая рубиновая магия превращает этот шифр в JSON, который D3.js может понять, и это все, что нужно сделать.

MATCH path=(p:Page {url:'/'})<-[:ON]-()-[:PREV*0..3]-()
RETURN EXTRACT(v in NODES(path)[1..LENGTH(path)+1] | v.url), count(path)
ORDER BY count(path) DESC
LIMIT 20

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

Мы развернем на Heroku

herokulogo

используя плагин GrapheneDB .
graphenelogo2

Я создал приложение Twilio, которое указывает на heroku:
Twilio-setup_app

… и установить мой номер, чтобы указать на приложение:

twilio_setup_number

Теперь у меня нет персонала, чтобы ответить на ваш звонок, и он точно не будет перенаправлен на мой мобильный телефон, поэтому вместо этого я решил, что конец дерева меню IVR будет воспроизводить небольшие звуковые фрагменты определенного «Отменили слишком рано научно-фантастический сериал» плюс пасхальное яйцо или две брошенные туда. Проблемы с жарой? Может быть, вы должны позвонить в: +1 ( нео ) 4j 1-7 411 .

Полный исходный код доступен на github как обычно. Я действительно хотел бы поблагодарить Ника Дингуолла, который сделал большую серию на эту тему для веб-трафика в своем блоге .